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 &);