From 4a9c907da7633ee24e54194a8a106e87a9ee3139 Mon Sep 17 00:00:00 2001 From: vganesan-nokia <67648637+vganesan-nokia@users.noreply.github.com> Date: Fri, 2 Jul 2021 13:38:13 -0400 Subject: [PATCH] [neighorch] VOQ encap index change handling (#1729) For the remote neighbors in the VOQ systems when there is change in the encap index (due to syncd restart), the previously programmed remote neighs should be re-written with the new changed encap index. The current voq system neigh handling api in neighorch only checks for the change of mac address. Because of this the change in the encap index is ignored. --- orchagent/neighorch.cpp | 124 +++++++++++++++++++++++++++++++++------- orchagent/neighorch.h | 2 + 2 files changed, 104 insertions(+), 22 deletions(-) diff --git a/orchagent/neighorch.cpp b/orchagent/neighorch.cpp index 6b3f2be658..4492b19993 100644 --- a/orchagent/neighorch.cpp +++ b/orchagent/neighorch.cpp @@ -783,16 +783,16 @@ bool NeighOrch::addNeighbor(const NeighborEntry &neighborEntry, const MacAddress MuxOrch* mux_orch = gDirectory.get(); bool hw_config = isHwConfigured(neighborEntry); - if (!hw_config && mux_orch->isNeighborActive(ip_address, macAddress, alias)) + if (gMySwitchType == "voq") { - if (gMySwitchType == "voq") + if (!addVoqEncapIndex(alias, ip_address, neighbor_attrs)) { - if (!addVoqEncapIndex(alias, ip_address, neighbor_attrs)) - { - return false; - } + return false; } + } + if (!hw_config && mux_orch->isNeighborActive(ip_address, macAddress, alias)) + { status = sai_neighbor_api->create_neighbor_entry(&neighbor_entry, (uint32_t)neighbor_attrs.size(), neighbor_attrs.data()); if (status != SAI_STATUS_SUCCESS) @@ -1230,8 +1230,43 @@ void NeighOrch::doVoqSystemNeighTask(Consumer &consumer) } if (m_syncdNeighbors.find(neighbor_entry) == m_syncdNeighbors.end() || - m_syncdNeighbors[neighbor_entry].mac != mac_address) + m_syncdNeighbors[neighbor_entry].mac != mac_address || + m_syncdNeighbors[neighbor_entry].voq_encap_index != encap_index) { + + if (m_syncdNeighbors.find(neighbor_entry) != m_syncdNeighbors.end() && + m_syncdNeighbors[neighbor_entry].voq_encap_index != encap_index) + { + + // Encap index changed. Set encap index attribute with new encap index + if (!updateVoqNeighborEncapIndex(neighbor_entry, encap_index)) + { + // Setting encap index failed. SAI does not support change of encap index for + // existing neighbors. Remove the neighbor but do not errase from consumer sync + // buffer. The next iteration will add the neighbor back with new encap index + + SWSS_LOG_NOTICE("VOQ encap index set failed for neighbor %s. Removing and re-adding", kfvKey(t).c_str()); + + //Remove neigh from SAI + if (removeNeighbor(neighbor_entry)) + { + //neigh successfully deleted from SAI. Set STATE DB to signal to remove entries from kernel + m_stateSystemNeighTable->del(state_key); + } + else + { + SWSS_LOG_ERROR("Failed to remove voq neighbor %s from SAI during encap index update", kfvKey(t).c_str()); + } + it++; + } + else + { + SWSS_LOG_NOTICE("VOQ encap index updated for neighbor %s", kfvKey(t).c_str()); + it = consumer.m_toSync.erase(it); + } + continue; + } + //Add neigh to SAI if (addNeighbor(neighbor_entry, mac_address)) { @@ -1467,6 +1502,27 @@ void NeighOrch::voqSyncAddNeigh(string &alias, IpAddress &ip_address, const MacA sai_attribute_t attr; sai_status_t status; + // Get the encap index and store it for handling change of + // encap index for remote neighbors synced via CHASSIS_APP_DB + + attr.id = SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX; + + status = sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, 1, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get neighbor attribute for %s on %s, rv:%d", ip_address.to_string().c_str(), alias.c_str(), status); + return; + } + + if (!attr.value.u32) + { + SWSS_LOG_ERROR("Invalid neighbor encap_index for %s on %s", ip_address.to_string().c_str(), alias.c_str()); + return; + } + + NeighborEntry nbrEntry = {ip_address, alias}; + m_syncdNeighbors[nbrEntry].voq_encap_index = attr.value.u32; + //Sync only local neigh. Confirm for the local neigh and //get the system port alias for key for syncing to CHASSIS_APP_DB Port port; @@ -1495,21 +1551,6 @@ void NeighOrch::voqSyncAddNeigh(string &alias, IpAddress &ip_address, const MacA return; } - attr.id = SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX; - - status = sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, 1, &attr); - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("Failed to get neighbor attribute for %s on %s, rv:%d", ip_address.to_string().c_str(), alias.c_str(), status); - return; - } - - if (!attr.value.u32) - { - SWSS_LOG_ERROR("Invalid neighbor encap_index for %s on %s", ip_address.to_string().c_str(), alias.c_str()); - return; - } - vector attrs; FieldValueTuple eiFv ("encap_index", to_string(attr.value.u32)); @@ -1555,3 +1596,42 @@ void NeighOrch::voqSyncDelNeigh(string &alias, IpAddress &ip_address) string key = alias + m_tableVoqSystemNeighTable->getTableNameSeparator().c_str() + ip_address.to_string(); m_tableVoqSystemNeighTable->del(key); } + +bool NeighOrch::updateVoqNeighborEncapIndex(const NeighborEntry &neighborEntry, uint32_t encap_index) +{ + SWSS_LOG_ENTER(); + + sai_status_t status; + IpAddress ip_address = neighborEntry.ip_address; + string alias = neighborEntry.alias; + + sai_object_id_t rif_id = m_intfsOrch->getRouterIntfsId(alias); + if (rif_id == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_INFO("Failed to get rif_id for %s", alias.c_str()); + return false; + } + + sai_neighbor_entry_t neighbor_entry; + neighbor_entry.rif_id = rif_id; + neighbor_entry.switch_id = gSwitchId; + copy(neighbor_entry.ip_address, ip_address); + + sai_attribute_t neighbor_attr; + neighbor_attr.id = SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX; + neighbor_attr.value.u32 = encap_index; + + status = sai_neighbor_api->set_neighbor_entry_attribute(&neighbor_entry, &neighbor_attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to update voq encap index for neighbor %s on %s, rv:%d", + ip_address.to_string().c_str(), alias.c_str(), status); + return false; + } + + SWSS_LOG_NOTICE("Updated voq encap index for neighbor %s on %s", ip_address.to_string().c_str(), alias.c_str()); + + m_syncdNeighbors[neighborEntry].voq_encap_index = encap_index; + + return true; +} diff --git a/orchagent/neighorch.h b/orchagent/neighorch.h index 8a3ec30c53..3b5867a949 100644 --- a/orchagent/neighorch.h +++ b/orchagent/neighorch.h @@ -27,6 +27,7 @@ struct NeighborData { MacAddress mac; bool hw_configured = false; // False means, entry is not written to HW + uint32_t voq_encap_index = 0; }; /* NeighborTable: NeighborEntry, neighbor MAC address */ @@ -108,6 +109,7 @@ class NeighOrch : public Orch, public Subject, public Observer bool addVoqEncapIndex(string &alias, IpAddress &ip, vector &neighbor_attrs); void voqSyncAddNeigh(string &alias, IpAddress &ip_address, const MacAddress &mac, sai_neighbor_entry_t &neighbor_entry); void voqSyncDelNeigh(string &alias, IpAddress &ip_address); + bool updateVoqNeighborEncapIndex(const NeighborEntry &neighborEntry, uint32_t encap_index); bool resolveNeighborEntry(const NeighborEntry &, const MacAddress &); void clearResolvedNeighborEntry(const NeighborEntry &);