void BcmWarmBootCache::clear()

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;
}