std::shared_ptr SaiSwitch::stateChangedImpl()

in fboss/agent/hw/sai/switch/SaiSwitch.cpp [479:753]


std::shared_ptr<SwitchState> SaiSwitch::stateChangedImpl(
    const StateDelta& delta,
    const LockPolicyT& lockPolicy) {
  // update switch settings first
  processSwitchSettingsChanged(delta, lockPolicy);

  processRemovedDelta(
      delta.getPortsDelta(),
      managerTable_->portManager(),
      lockPolicy,
      &SaiPortManager::removePort);
  processChangedDelta(
      delta.getPortsDelta(),
      managerTable_->portManager(),
      lockPolicy,
      &SaiPortManager::changePort);
  processAddedDelta(
      delta.getPortsDelta(),
      managerTable_->portManager(),
      lockPolicy,
      &SaiPortManager::addPort);
  processDelta(
      delta.getVlansDelta(),
      managerTable_->vlanManager(),
      lockPolicy,
      &SaiVlanManager::changeVlan,
      &SaiVlanManager::addVlan,
      &SaiVlanManager::removeVlan);

  // LAGs
  processDelta(
      delta.getAggregatePortsDelta(),
      managerTable_->lagManager(),
      lockPolicy,
      &SaiLagManager::changeLag,
      &SaiLagManager::addLag,
      &SaiLagManager::removeLag);

  if (platform_->getAsic()->isSupported(HwAsic::Feature::BRIDGE_PORT_8021Q)) {
    // Add/Change bridge ports
    DeltaFunctions::forEachChanged(
        delta.getPortsDelta(),
        [&](const std::shared_ptr<Port>& oldPort,
            const std::shared_ptr<Port>& newPort) {
          auto portID = oldPort->getID();
          [[maybe_unused]] const auto& lock = lockPolicy.lock();
          if (managerTable_->lagManager().isLagMember(portID)) {
            // if port is member of lag, ignore it
            return;
          }
          managerTable_->portManager().changeBridgePort(oldPort, newPort);
        });

    DeltaFunctions::forEachAdded(
        delta.getPortsDelta(), [&](const std::shared_ptr<Port>& newPort) {
          auto portID = newPort->getID();
          [[maybe_unused]] const auto& lock = lockPolicy.lock();
          if (managerTable_->lagManager().isLagMember(portID)) {
            // if port is member of lag, ignore it
            return;
          }
          managerTable_->portManager().addBridgePort(newPort);
        });

    DeltaFunctions::forEachChanged(
        delta.getAggregatePortsDelta(),
        [&](const std::shared_ptr<AggregatePort>& oldAggPort,
            const std::shared_ptr<AggregatePort>& newAggPort) {
          [[maybe_unused]] const auto& lock = lockPolicy.lock();
          managerTable_->lagManager().changeBridgePort(oldAggPort, newAggPort);
        });

    DeltaFunctions::forEachAdded(
        delta.getAggregatePortsDelta(),
        [&](const std::shared_ptr<AggregatePort>& newAggPort) {
          [[maybe_unused]] const auto& lock = lockPolicy.lock();
          managerTable_->lagManager().addBridgePort(newAggPort);
        });
  }
  if (platform_->getAsic()->isSupported(HwAsic::Feature::QOS_MAP_GLOBAL)) {
    processDefaultDataPlanePolicyDelta(
        delta, managerTable_->switchManager(), lockPolicy);
  } else {
    processDefaultDataPlanePolicyDelta(
        delta, managerTable_->portManager(), lockPolicy);
  }

  processDelta(
      delta.getIntfsDelta(),
      managerTable_->routerInterfaceManager(),
      lockPolicy,
      &SaiRouterInterfaceManager::changeRouterInterface,
      &SaiRouterInterfaceManager::addRouterInterface,
      &SaiRouterInterfaceManager::removeRouterInterface);

  for (const auto& vlanDelta : delta.getVlansDelta()) {
    processDelta(
        vlanDelta.getArpDelta(),
        managerTable_->neighborManager(),
        lockPolicy,
        &SaiNeighborManager::changeNeighbor<ArpEntry>,
        &SaiNeighborManager::addNeighbor<ArpEntry>,
        &SaiNeighborManager::removeNeighbor<ArpEntry>);

    processDelta(
        vlanDelta.getNdpDelta(),
        managerTable_->neighborManager(),
        lockPolicy,
        &SaiNeighborManager::changeNeighbor<NdpEntry>,
        &SaiNeighborManager::addNeighbor<NdpEntry>,
        &SaiNeighborManager::removeNeighbor<NdpEntry>);

    processDelta(
        vlanDelta.getMacDelta(),
        managerTable_->fdbManager(),
        lockPolicy,
        &SaiFdbManager::changeMac,
        &SaiFdbManager::addMac,
        &SaiFdbManager::removeMac);
  }

  auto processV4RoutesDelta = [this, &lockPolicy](
                                  RouterID rid, const auto& routesDelta) {
    processDelta(
        routesDelta,
        managerTable_->routeManager(),
        lockPolicy,
        &SaiRouteManager::changeRoute<folly::IPAddressV4>,
        &SaiRouteManager::addRoute<folly::IPAddressV4>,
        &SaiRouteManager::removeRoute<folly::IPAddressV4>,
        rid);
  };

  auto processV6RoutesDelta = [this, &lockPolicy](
                                  RouterID rid, const auto& routesDelta) {
    processDelta(
        routesDelta,
        managerTable_->routeManager(),
        lockPolicy,
        &SaiRouteManager::changeRoute<folly::IPAddressV6>,
        &SaiRouteManager::addRoute<folly::IPAddressV6>,
        &SaiRouteManager::removeRoute<folly::IPAddressV6>,
        rid);
  };

  for (const auto& routeDelta : delta.getFibsDelta()) {
    auto routerID = routeDelta.getOld() ? routeDelta.getOld()->getID()
                                        : routeDelta.getNew()->getID();
    processV4RoutesDelta(
        routerID, routeDelta.getFibDelta<folly::IPAddressV4>());
    processV6RoutesDelta(
        routerID, routeDelta.getFibDelta<folly::IPAddressV6>());
  }
  {
    auto controlPlaneDelta = delta.getControlPlaneDelta();
    if (*controlPlaneDelta.getOld() != *controlPlaneDelta.getNew()) {
      [[maybe_unused]] const auto& lock = lockPolicy.lock();
      managerTable_->hostifManager().processHostifDelta(controlPlaneDelta);
    }
  }

  processDelta(
      delta.getLabelForwardingInformationBaseDelta(),
      managerTable_->inSegEntryManager(),
      lockPolicy,
      &SaiInSegEntryManager::processChangedInSegEntry,
      &SaiInSegEntryManager::processAddedInSegEntry,
      &SaiInSegEntryManager::processRemovedInSegEntry);
  processDelta(
      delta.getLoadBalancersDelta(),
      managerTable_->switchManager(),
      lockPolicy,
      &SaiSwitchManager::changeLoadBalancer,
      &SaiSwitchManager::addOrUpdateLoadBalancer,
      &SaiSwitchManager::removeLoadBalancer);

  /*
   * Add/update mirrors before processing ACL, as ACLs with action
   * INGRESS/EGRESS Mirror rely on the Mirror being created.
   */
  processDelta(
      delta.getMirrorsDelta(),
      managerTable_->mirrorManager(),
      lockPolicy,
      &SaiMirrorManager::changeMirror,
      &SaiMirrorManager::addMirror,
      &SaiMirrorManager::removeMirror);

  if (FLAGS_enable_acl_table_group &&
      platform_->getAsic()->isSupported(HwAsic::Feature::MULTIPLE_ACL_TABLES)) {
    processDelta(
        delta.getAclTableGroupsDelta(),
        managerTable_->aclTableGroupManager(),
        lockPolicy,
        &SaiAclTableGroupManager::changedAclTableGroup,
        &SaiAclTableGroupManager::addAclTableGroup,
        &SaiAclTableGroupManager::removeAclTableGroup);

    if (delta.getAclTableGroupsDelta().getNew()) {
      // Process delta for the entries of each table in the new state
      for (const auto& tableGroup : *delta.getAclTableGroupsDelta().getNew()) {
        auto aclStage = tableGroup->getID();

        processDelta(
            delta.getAclTablesDelta(aclStage),
            managerTable_->aclTableManager(),
            lockPolicy,
            &SaiAclTableManager::changedAclTable,
            &SaiAclTableManager::addAclTable,
            &SaiAclTableManager::removeAclTable,
            aclStage);

        if (delta.getAclTablesDelta(aclStage).getNew()) {
          // Process delta for the entries of each table in the new state
          for (const auto& table :
               *delta.getAclTablesDelta(aclStage).getNew()) {
            auto tableName = table->getID();
            processDelta(
                delta.getAclsDelta(aclStage, tableName),
                managerTable_->aclTableManager(),
                lockPolicy,
                &SaiAclTableManager::changedAclEntry,
                &SaiAclTableManager::addAclEntry,
                &SaiAclTableManager::removeAclEntry,
                tableName);
          }
        }
      }
    }
  } else {
    std::set<cfg::AclTableQualifier> oldRequiredQualifiers{};
    std::set<cfg::AclTableQualifier> newRequiredQualifiers{};
    if (delta.getAclsDelta().getOld()) {
      oldRequiredQualifiers =
          delta.getAclsDelta().getOld()->requiredQualifiers();
    }
    if (delta.getAclsDelta().getNew()) {
      newRequiredQualifiers =
          delta.getAclsDelta().getNew()->requiredQualifiers();
    }
    if (!oldRequiredQualifiers.empty() &&
        oldRequiredQualifiers != newRequiredQualifiers &&
        platform_->getAsic()->isSupported(
            HwAsic::Feature::SAI_ACL_TABLE_UPDATE) &&
        !managerTable_->aclTableManager()
             .areQualifiersSupportedInDefaultAclTable(newRequiredQualifiers)) {
      // qualifiers changed and default acl table doesn't support all of them,
      // remove default acl table and add a new one. table removal should
      // clear acl entries too
      managerTable_->switchManager().resetIngressAcl();
      managerTable_->aclTableManager().removeDefaultAclTable();
      managerTable_->aclTableManager().addDefaultAclTable();
      managerTable_->switchManager().setIngressAcl();
    }

    processDelta(
        delta.getAclsDelta(),
        managerTable_->aclTableManager(),
        lockPolicy,
        &SaiAclTableManager::changedAclEntry,
        &SaiAclTableManager::addAclEntry,
        &SaiAclTableManager::removeAclEntry,
        kAclTable1);
  }

  if (platform_->getAsic()->isSupported(
          HwAsic::Feature::RESOURCE_USAGE_STATS)) {
    updateResourceUsage(lockPolicy);
  }

  // Process link state change delta and update the LED status
  processLinkStateChangeDelta(delta, lockPolicy);

  return delta.newState();
}