in fboss/agent/hw/bcm/BcmWarmBootCache.cpp [763:973]
void BcmWarmBootCache::clear() {
// Get rid of all unclaimed entries. The order is important here
// since we want to delete entries only after there are no more
// references to them.
XLOG(DBG1) << "Warm boot: removing unreferenced entries";
dumpedSwSwitchState_.reset();
hwSwitchEcmp2EgressIds_.clear();
// First delete routes (fully qualified and others).
//
// Nothing references routes, but routes reference ecmp egress and egress
// entries which are deleted later
for (auto vrfPfxAndRoute : vrfPrefix2Route_) {
const std::string& routeInfo = folly::to<std::string>(
"unreferenced route in vrf : ",
std::get<0>(vrfPfxAndRoute.first),
" for prefix : ",
std::get<1>(vrfPfxAndRoute.first),
"/",
std::get<2>(vrfPfxAndRoute.first));
XLOG(DBG1) << "Deleting an " << routeInfo;
auto rv = bcm_l3_route_delete(hw_->getUnit(), &(vrfPfxAndRoute.second));
XLOG_IF(WARNING, rv == BCM_E_NOT_FOUND)
<< "Trying to delete a nonexistent " << routeInfo << ", ignore it.";
if (rv != BCM_E_NOT_FOUND) {
bcmLogFatal(rv, hw_, "failed to delete an", routeInfo);
}
}
vrfPrefix2Route_.clear();
for (auto vrfIPAndRoute : vrfAndIP2Route_) {
const std::string& routeInfo = folly::to<std::string>(
"fully qualified unreferenced route in vrf:",
vrfIPAndRoute.first.first,
" prefix: ",
vrfIPAndRoute.first.second);
XLOG(DBG1) << "Deleting a" << routeInfo;
auto rv = bcm_l3_route_delete(hw_->getUnit(), &(vrfIPAndRoute.second));
XLOG_IF(WARNING, rv == BCM_E_NOT_FOUND)
<< "Trying to delete a nonexistent " << routeInfo << ", ignore it.";
if (rv != BCM_E_NOT_FOUND) {
bcmLogFatal(rv, hw_, "failed to delete a", routeInfo);
}
}
vrfAndIP2Route_.clear();
// purge any lingering label FIB entries
removeUnclaimedLabelSwitchActions();
// Delete bcm host entries. Nobody references bcm hosts, but
// hosts reference egress objects
for (auto vrfIpAndHost : vrfIp2Host_) {
XLOG(DBG1) << "Deleting host entry in vrf: " << vrfIpAndHost.first.first
<< " for : " << vrfIpAndHost.first.second;
auto rv = bcm_l3_host_delete(hw_->getUnit(), &vrfIpAndHost.second);
bcmLogFatal(
rv,
hw_,
"failed to delete host entry in vrf: ",
vrfIpAndHost.first.first,
" for : ",
vrfIpAndHost.first.second);
}
vrfIp2Host_.clear();
// Both routes and host entries (which have been deleted earlier) can refer
// to ecmp egress objects. Ecmp egress objects in turn refer to egress
// objects which we delete later
for (auto idsAndEcmp : egressIds2Ecmp_) {
auto& ecmp = idsAndEcmp.second;
XLOG(DBG1) << "Deleting ecmp egress object " << ecmp.ecmp_intf
<< " pointing to : " << toEgressId2WeightStr(idsAndEcmp.first);
int rv;
if (hw_->getPlatform()->getAsic()->isSupported(HwAsic::Feature::HSDK)) {
rv = bcm_l3_ecmp_destroy(hw_->getUnit(), ecmp.ecmp_intf);
} else {
rv = bcm_l3_egress_ecmp_destroy(hw_->getUnit(), &ecmp);
}
bcmLogFatal(
rv,
hw_,
"failed to destroy ecmp egress object :",
ecmp.ecmp_intf,
" referring to ",
toEgressId2WeightStr(idsAndEcmp.first));
}
egressIds2Ecmp_.clear();
// Delete bcm egress entries. These are referenced by routes, ecmp egress
// and host objects all of which we deleted above. Egress objects in turn
// my point to a interface which we delete later
for (auto egressIdAndEgress : egressId2Egress_) {
// This is not used yet
XLOG(DBG1) << "Deleting egress object: " << egressIdAndEgress.first;
auto rv = bcm_l3_egress_destroy(hw_->getUnit(), egressIdAndEgress.first);
bcmLogFatal(
rv, hw_, "failed to destroy egress object ", egressIdAndEgress.first);
}
egressId2Egress_.clear();
// delete any MPLS tunnels
removeUnclaimedLabeledTunnels();
// Delete interfaces
for (auto vlanMacAndIntf : vlanAndMac2Intf_) {
XLOG(DBG1) << "Deleting l3 interface for vlan: "
<< vlanMacAndIntf.first.first
<< " and mac : " << vlanMacAndIntf.first.second;
auto rv = bcm_l3_intf_delete(hw_->getUnit(), &vlanMacAndIntf.second);
bcmLogFatal(
rv,
hw_,
"failed to delete l3 interface for vlan: ",
vlanMacAndIntf.first.first,
" and mac : ",
vlanMacAndIntf.first.second);
}
vlanAndMac2Intf_.clear();
// Delete stations
for (auto vlanAndStation : vlan2Station_) {
XLOG(DBG1) << "Deleting station for vlan : " << vlanAndStation.first;
auto stationId =
hw_->getPlatform()->getAsic()->getStationID(vlanAndStation.first);
auto rv = bcm_l2_station_delete(hw_->getUnit(), stationId);
bcmLogFatal(
rv, hw_, "failed to delete station for vlan : ", vlanAndStation.first);
}
vlan2Station_.clear();
bcm_vlan_t defaultVlan;
auto rv = bcm_vlan_default_get(hw_->getUnit(), &defaultVlan);
bcmLogFatal(rv, hw_, "failed to get default VLAN");
// Finally delete the vlans
for (auto vlanItr = vlan2VlanInfo_.begin();
vlanItr != vlan2VlanInfo_.end();) {
if (defaultVlan == vlanItr->first) {
++vlanItr;
continue; // Can't delete the default vlan
}
XLOG(DBG1) << "Deleting vlan : " << vlanItr->first;
auto rv = bcm_vlan_destroy(hw_->getUnit(), vlanItr->first);
bcmLogFatal(rv, hw_, "failed to destroy vlan: ", vlanItr->first);
vlanItr = vlan2VlanInfo_.erase(vlanItr);
}
egressId2WeightInWarmBootFile_.clear();
vrfIp2EgressFromBcmHostInWarmBootFile_.clear();
// Detach the unclaimed bcm acl stats
flat_set<BcmAclStatHandle> statsUsed;
for (auto aclStatItr = aclEntry2AclStat_.begin();
aclStatItr != aclEntry2AclStat_.end();
++aclStatItr) {
auto& aclStatStatus = aclStatItr->second;
if (!aclStatStatus.claimed) {
XLOG(DBG1) << "Detaching unclaimed acl_stat=" << aclStatStatus.stat
<< "from acl=" << aclStatItr->first;
BcmAclStat::detach(hw_, aclStatItr->first, aclStatStatus.stat);
} else {
statsUsed.insert(aclStatStatus.stat);
}
}
// Delete the unclaimed bcm acl stats
for (auto statItr : aclEntry2AclStat_) {
auto statHandle = statItr.second.stat;
if (statsUsed.find(statHandle) == statsUsed.end()) {
XLOG(DBG1) << "Deleting unclaimed acl_stat=" << statHandle;
BcmAclStat::destroy(hw_, statHandle);
// add the stat to the set to prevent this loop from attempting to
// delete the same stat twice
statsUsed.insert(statHandle);
}
}
aclEntry2AclStat_.clear();
// Delete acls, since acl(field process) doesn't support
// bcm, we call BcmAclTable to remove the unclaimed acls
XLOG(DBG1) << "Unclaimed acl count=" << priority2BcmAclEntryHandle_.size();
for (auto aclItr : priority2BcmAclEntryHandle_) {
XLOG(DBG1) << "Deleting unclaimed acl: prio=" << aclItr.first
<< ", handle=" << aclItr.second;
removeBcmAcl(aclItr.second);
}
priority2BcmAclEntryHandle_.clear();
bool useHSDK = (dynamic_cast<const BcmSwitch*>(hw_))->useHSDK();
for (auto reasonToQueueEntry : index2ReasonToQueue_) {
const auto index = reasonToQueueEntry.first;
XLOG(DBG1) << "Deleting rx reason to queue entry: index=" << index
<< ", reason="
<< apache::thrift::util::enumNameSafe(
*reasonToQueueEntry.second.rxReason())
<< ", queue=" << *reasonToQueueEntry.second.queueId();
if (!useHSDK) {
rv = bcm_rx_cosq_mapping_delete(hw_->getUnit(), index);
} else {
bcm_rx_cosq_mapping_t cosqMap;
bcm_rx_cosq_mapping_t_init(&cosqMap);
cosqMap.index = index;
rv = BcmControlPlane::rxCosqMappingExtendedDelete(
hw_->getUnit(), &cosqMap);
}
bcmCheckError(rv, "failed to delete CPU cosq mapping for index ", index);
}
index2ReasonToQueue_.clear();
/* remove unclaimed mirrors and mirrored ports/acls, if any */
checkUnclaimedMirrors();
checkUnclaimedQosMaps();
ptpTcEnabled_ = std::nullopt;
}