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