in fboss/agent/ApplyThriftConfig.cpp [385:685]
shared_ptr<SwitchState> ThriftConfigApplier::run() {
new_ = orig_->clone();
bool changed = false;
{
auto newSwitchSettings = updateSwitchSettings();
if (newSwitchSettings) {
new_->resetSwitchSettings(std::move(newSwitchSettings));
changed = true;
}
}
{
bool qcmChanged = false;
auto newQcmConfig = updateQcmCfg(&qcmChanged);
if (qcmChanged) {
new_->resetQcmCfg(newQcmConfig);
changed = true;
}
}
{
auto newControlPlane = updateControlPlane();
if (newControlPlane) {
new_->resetControlPlane(std::move(newControlPlane));
changed = true;
}
}
processVlanPorts();
{
bool bufferPoolConfigChanged = false;
auto newBufferPoolCfg = updateBufferPoolConfigs(&bufferPoolConfigChanged);
if (bufferPoolConfigChanged) {
new_->resetBufferPoolCfgs(newBufferPoolCfg);
changed = true;
}
}
{
auto newPorts = updatePorts(new_->getTransceivers());
if (newPorts) {
new_->resetPorts(std::move(newPorts));
changed = true;
}
}
{
auto newAggPorts = updateAggregatePorts();
if (newAggPorts) {
new_->resetAggregatePorts(std::move(newAggPorts));
changed = true;
}
}
// updateMirrors must be called after updatePorts, mirror needs ports!
{
auto newMirrors = updateMirrors();
if (newMirrors) {
new_->resetMirrors(std::move(newMirrors));
changed = true;
}
}
// updateAcls must be called after updateMirrors, acls may need mirror!
{
if (FLAGS_enable_acl_table_group) {
auto newAclTableGroups = updateAclTableGroups();
if (newAclTableGroups) {
new_->resetAclTableGroups(std::move(newAclTableGroups));
changed = true;
}
} else {
auto newAcls = updateAcls(cfg::AclStage::INGRESS, *cfg_->acls());
if (newAcls) {
new_->resetAcls(std::move(newAcls));
changed = true;
}
}
}
{
auto newQosPolicies = updateQosPolicies();
if (newQosPolicies) {
new_->resetQosPolicies(std::move(newQosPolicies));
changed = true;
}
}
// reset the default qos policy
{
auto newDefaultQosPolicy = updateDataplaneDefaultQosPolicy();
if (new_->getDefaultDataPlaneQosPolicy() != newDefaultQosPolicy) {
new_->setDefaultDataPlaneQosPolicy(newDefaultQosPolicy);
changed = true;
}
}
{
auto newIntfs = updateInterfaces();
if (newIntfs) {
new_->resetIntfs(std::move(newIntfs));
changed = true;
}
}
// Note: updateInterfaces() must be called before updateVlans(),
// as updateInterfaces() populates the vlanInterfaces_ data structure.
{
auto newVlans = updateVlans();
if (newVlans) {
new_->resetVlans(std::move(newVlans));
changed = true;
}
}
if (routeUpdater_) {
routeUpdater_->setRoutesToConfig(
intfRouteTables_,
*cfg_->staticRoutesWithNhops(),
*cfg_->staticRoutesToNull(),
*cfg_->staticRoutesToCPU(),
*cfg_->staticIp2MplsRoutes(),
*cfg_->staticMplsRoutesWithNhops(),
*cfg_->staticMplsRoutesToNull(),
*cfg_->staticMplsRoutesToCPU());
} else if (rib_) {
auto newFibs = updateForwardingInformationBaseContainers();
if (newFibs) {
new_->resetForwardingInformationBases(newFibs);
changed = true;
}
rib_->reconfigure(
intfRouteTables_,
*cfg_->staticRoutesWithNhops(),
*cfg_->staticRoutesToNull(),
*cfg_->staticRoutesToCPU(),
*cfg_->staticIp2MplsRoutes(),
*cfg_->staticMplsRoutesWithNhops(),
*cfg_->staticMplsRoutesToNull(),
*cfg_->staticMplsRoutesToCPU(),
&updateFibFromConfig,
static_cast<void*>(&new_));
} else {
// switch state UTs don't necessary care about RIB updates
XLOG(WARNING)
<< " Ignoring config updates to rib, should never happen outside of tests";
}
// resolving mpls next hops may need interfaces to be setup
// process static mpls routes after processing interfaces
auto labelFib = updateStaticMplsRoutes(
*cfg_->staticMplsRoutesWithNhops(),
*cfg_->staticMplsRoutesToNull(),
*cfg_->staticMplsRoutesToNull());
if (labelFib) {
new_->resetLabelForwardingInformationBase(labelFib);
changed = true;
}
auto newVlans = new_->getVlans();
VlanID dfltVlan(*cfg_->defaultVlan());
if (orig_->getDefaultVlan() != dfltVlan) {
if (newVlans->getVlanIf(dfltVlan) == nullptr) {
throw FbossError("Default VLAN ", dfltVlan, " does not exist");
}
new_->setDefaultVlan(dfltVlan);
changed = true;
}
// Make sure all interfaces refer to valid VLANs.
for (const auto& vlanInfo : vlanInterfaces_) {
if (newVlans->getVlanIf(vlanInfo.first) == nullptr) {
throw FbossError(
"Interface ",
*(vlanInfo.second.interfaces.begin()),
" refers to non-existent VLAN ",
vlanInfo.first);
}
// Make sure there is a one-to-one map between vlan and interface
// Remove this sanity check if multiple interfaces are allowed per vlans
auto& entry = vlanInterfaces_[vlanInfo.first];
if (entry.interfaces.size() != 1) {
auto cpu_vlan = new_->getDefaultVlan();
if (vlanInfo.first != cpu_vlan) {
throw FbossError(
"Vlan ",
vlanInfo.first,
" refers to ",
entry.interfaces.size(),
" interfaces ");
}
}
}
{
auto pfcWatchdogRecoveryAction = getPfcWatchdogRecoveryAction();
if (pfcWatchdogRecoveryAction != orig_->getPfcWatchdogRecoveryAction()) {
new_->setPfcWatchdogRecoveryAction(pfcWatchdogRecoveryAction);
changed = true;
}
}
std::chrono::seconds arpAgerInterval(*cfg_->arpAgerInterval());
if (orig_->getArpAgerInterval() != arpAgerInterval) {
new_->setArpAgerInterval(arpAgerInterval);
changed = true;
}
std::chrono::seconds arpTimeout(*cfg_->arpTimeoutSeconds());
if (orig_->getArpTimeout() != arpTimeout) {
new_->setArpTimeout(arpTimeout);
// TODO(aeckert): add ndpTimeout field to SwitchConfig. For now use the same
// timeout for both ARP and NDP
new_->setNdpTimeout(arpTimeout);
changed = true;
}
uint32_t maxNeighborProbes(*cfg_->maxNeighborProbes());
if (orig_->getMaxNeighborProbes() != maxNeighborProbes) {
new_->setMaxNeighborProbes(maxNeighborProbes);
changed = true;
}
auto oldDhcpV4RelaySrc = orig_->getDhcpV4RelaySrc();
auto newDhcpV4RelaySrc = cfg_->dhcpRelaySrcOverrideV4()
? IPAddressV4(*cfg_->dhcpRelaySrcOverrideV4())
: IPAddressV4();
if (oldDhcpV4RelaySrc != newDhcpV4RelaySrc) {
new_->setDhcpV4RelaySrc(newDhcpV4RelaySrc);
changed = true;
}
auto oldDhcpV6RelaySrc = orig_->getDhcpV6RelaySrc();
auto newDhcpV6RelaySrc = cfg_->dhcpRelaySrcOverrideV6()
? IPAddressV6(*cfg_->dhcpRelaySrcOverrideV6())
: IPAddressV6("::");
if (oldDhcpV6RelaySrc != newDhcpV6RelaySrc) {
new_->setDhcpV6RelaySrc(newDhcpV6RelaySrc);
changed = true;
}
auto oldDhcpV4ReplySrc = orig_->getDhcpV4ReplySrc();
auto newDhcpV4ReplySrc = cfg_->dhcpReplySrcOverrideV4()
? IPAddressV4(*cfg_->dhcpReplySrcOverrideV4())
: IPAddressV4();
if (oldDhcpV4ReplySrc != newDhcpV4ReplySrc) {
new_->setDhcpV4ReplySrc(newDhcpV4ReplySrc);
changed = true;
}
auto oldDhcpV6ReplySrc = orig_->getDhcpV6ReplySrc();
auto newDhcpV6ReplySrc = cfg_->dhcpReplySrcOverrideV6()
? IPAddressV6(*cfg_->dhcpReplySrcOverrideV6())
: IPAddressV6("::");
if (oldDhcpV6ReplySrc != newDhcpV6ReplySrc) {
new_->setDhcpV6ReplySrc(newDhcpV6ReplySrc);
changed = true;
}
std::chrono::seconds staleEntryInterval(*cfg_->staleEntryInterval());
if (orig_->getStaleEntryInterval() != staleEntryInterval) {
new_->setStaleEntryInterval(staleEntryInterval);
changed = true;
}
// Add sFlow collectors
{
auto newCollectors = updateSflowCollectors();
if (newCollectors) {
new_->resetSflowCollectors(std::move(newCollectors));
changed = true;
}
}
{
LoadBalancerConfigApplier loadBalancerConfigApplier(
orig_->getLoadBalancers(), cfg_->get_loadBalancers(), platform_);
auto newLoadBalancers = loadBalancerConfigApplier.updateLoadBalancers();
if (newLoadBalancers) {
new_->resetLoadBalancers(std::move(newLoadBalancers));
changed = true;
}
}
// normalizer to refresh counter tags
if (auto normalizer = Normalizer::getInstance()) {
normalizer->reloadCounterTags(*cfg_);
} else {
XLOG(ERR)
<< "Normalizer failed to initialize, skipping loading counter tags";
}
if (!changed) {
return nullptr;
}
return new_;
}