void BcmWarmBootCache::populate()

in fboss/agent/hw/bcm/BcmWarmBootCache.cpp [448:585]


void BcmWarmBootCache::populate(const folly::dynamic& warmBootState) {
  populateFromWarmBootState(warmBootState);
  bcm_vlan_data_t* vlanList = nullptr;
  int vlanCount = 0;
  SCOPE_EXIT {
    bcm_vlan_list_destroy(hw_->getUnit(), vlanList, vlanCount);
  };
  auto rv = bcm_vlan_list(hw_->getUnit(), &vlanList, &vlanCount);
  bcmCheckError(rv, "Unable to get vlan information");
  for (auto i = 0; i < vlanCount; ++i) {
    bcm_vlan_data_t& vlanData = vlanList[i];
    int portCount = 0;
    BCM_PBMP_COUNT(vlanData.port_bitmap, portCount);
    XLOG(DBG1) << "Got vlan : " << vlanData.vlan_tag << " with : " << portCount
               << " ports";
    // TODO: Investigate why port_bitmap contains
    // the untagged ports rather than ut_port_bitmap
    vlan2VlanInfo_.insert(make_pair(
        BcmSwitch::getVlanId(vlanData.vlan_tag),
        VlanInfo(
            VlanID(vlanData.vlan_tag),
            vlanData.port_bitmap,
            vlanData.port_bitmap)));
    bcm_l3_intf_t l3Intf;
    bcm_l3_intf_t_init(&l3Intf);
    // there can be more than one interfaces per vlan, such as one l3 intf
    // and other MPLS tunnels. There is no clear way to identify which is
    // which. so keeping track of l3 interfaces in warmboot state file
    // look for l3 intf ID in warmboot state file and try to extract it.
    l3Intf.l3a_vid = vlanData.vlan_tag;
    bool intfFound = false;
    auto iter = vlan2BcmIfIdInWarmBootFile_.find(VlanID(vlanData.vlan_tag));
    if (iter != vlan2BcmIfIdInWarmBootFile_.end()) {
      l3Intf.l3a_intf_id = iter->second;
      l3Intf.l3a_flags = BCM_L3_WITH_ID;
      rv = bcm_l3_intf_get(hw_->getUnit(), &l3Intf);
    } else {
      // this can happen for vlan id 1, a special vlan which is returned by
      // bcm_vlan_list, this vlan has all ports which has no vlan associated
      // it also has port 0 if all front panel ports are associated with some
      // vlan. this vlan won't be in vlan2BcmIfIdInWarmBootFile_
      rv = bcm_l3_intf_find_vlan(hw_->getUnit(), &l3Intf);
    }
    if (rv != BCM_E_NOT_FOUND) {
      bcmCheckError(rv, "failed to find interface for ", vlanData.vlan_tag);
      intfFound = true;
      vlanAndMac2Intf_[make_pair(
          BcmSwitch::getVlanId(l3Intf.l3a_vid),
          macFromBcm(l3Intf.l3a_mac_addr))] = l3Intf;
      XLOG(DBG1) << "Found l3 interface for vlan : " << vlanData.vlan_tag;
    }
    if (intfFound) {
      bcm_l2_station_t l2Station;
      bcm_l2_station_t_init(&l2Station);
      auto stationId =
          hw_->getPlatform()->getAsic()->getStationID(l3Intf.l3a_vid);
      rv = bcm_l2_station_get(hw_->getUnit(), stationId, &l2Station);
      if (!BCM_FAILURE(rv)) {
        XLOG(DBG1) << " Found l2 station with id : " << l3Intf.l3a_vid;
        vlan2Station_[VlanID(vlanData.vlan_tag)] = l2Station;
      } else {
        XLOG(DBG1) << "Could not get l2 station for vlan : "
                   << vlanData.vlan_tag;
      }
    }
  }
  bcm_l3_info_t l3Info;
  bcm_l3_info_t_init(&l3Info);
  bcm_l3_info(hw_->getUnit(), &l3Info);
  if (hw_->getPlatform()->getAsic()->isSupported(HwAsic::Feature::HOSTTABLE)) {
    // Traverse V4 hosts
    rv = bcm_l3_host_traverse(
        hw_->getUnit(),
        0,
        0,
        l3Info.l3info_max_host,
        hostTraversalCallback,
        this);
    bcmCheckError(rv, "Failed to traverse v4 hosts");
    // Traverse V6 hosts
    rv = bcm_l3_host_traverse(
        hw_->getUnit(),
        BCM_L3_IP6,
        0,
        // Diag shell uses this for getting # of v6 host entries
        l3Info.l3info_max_host / 2,
        hostTraversalCallback,
        this);
    bcmCheckError(rv, "Failed to traverse v6 hosts");
  }
  // Traverse V4 routes
  rv = bcm_l3_route_traverse(
      hw_->getUnit(),
      0,
      0,
      l3Info.l3info_max_route,
      routeTraversalCallback,
      this);
  bcmCheckError(rv, "Failed to traverse v4 routes");
  // Traverse V6 routes
  rv = bcm_l3_route_traverse(
      hw_->getUnit(),
      BCM_L3_IP6,
      0,
      // Diag shell uses this for getting # of v6 route entries
      l3Info.l3info_max_route / 2,
      routeTraversalCallback,
      this);
  bcmCheckError(rv, "Failed to traverse v6 routes");
  // Get egress entries.
  rv = bcm_l3_egress_traverse(hw_->getUnit(), egressTraversalCallback, this);
  bcmCheckError(rv, "Failed to traverse egress");
  // Traverse ecmp egress entries
  if (hw_->getPlatform()->getAsic()->isSupported(HwAsic::Feature::HSDK)) {
    rv = bcm_l3_ecmp_traverse(
        hw_->getUnit(),
        ecmpEgressTraversalCallback<bcm_l3_ecmp_member_t>,
        this);
  } else {
    rv = bcm_l3_egress_ecmp_traverse(
        hw_->getUnit(), ecmpEgressTraversalCallback<bcm_if_t>, this);
  }
  bcmCheckError(rv, "Failed to traverse ecmp egress");

  // populate acls, acl stats
  populateAcls(
      hw_->getPlatform()->getAsic()->getDefaultACLGroupID(),
      this->aclEntry2AclStat_,
      this->priority2BcmAclEntryHandle_);

  populateRtag7State();
  populateMirrors();
  populateMirroredPorts();
  populateQosMaps();
  populateLabelSwitchActions();
  populateSwitchSettings();
  populateRxReasonToQueue();
}