in fboss/agent/ApplyThriftConfig.cpp [2101:2257]
std::shared_ptr<AclMap> ThriftConfigApplier::updateAcls(
cfg::AclStage aclStage,
std::vector<cfg::AclEntry> configEntries,
std::optional<std::string> tableName) {
AclMap::NodeContainer newAcls;
bool changed = false;
int numExistingProcessed = 0;
int priority = kAclStartPriority;
int cpuPriority = 1;
// Start with the DROP acls, these should have highest priority
auto acls = folly::gen::from(configEntries) |
folly::gen::filter([](const cfg::AclEntry& entry) {
return *entry.actionType() == cfg::AclActionType::DENY;
}) |
folly::gen::map([&](const cfg::AclEntry& entry) {
auto acl = updateAcl(
aclStage,
entry,
priority++,
&numExistingProcessed,
&changed,
tableName);
return std::make_pair(acl->getID(), acl);
}) |
folly::gen::appendTo(newAcls);
// Let's get a map of acls to name so we don't have to search the acl list
// for every new use
flat_map<std::string, const cfg::AclEntry*> aclByName;
folly::gen::from(configEntries) |
folly::gen::map([](const cfg::AclEntry& acl) {
return std::make_pair(*acl.name(), &acl);
}) |
folly::gen::appendTo(aclByName);
flat_map<std::string, const cfg::TrafficCounter*> counterByName;
folly::gen::from(*cfg_->trafficCounters()) |
folly::gen::map([](const cfg::TrafficCounter& counter) {
return std::make_pair(*counter.name(), &counter);
}) |
folly::gen::appendTo(counterByName);
// Generates new acls from template
auto addToAcls = [&](const cfg::TrafficPolicyConfig& policy,
bool isCoppAcl = false)
-> const std::vector<std::pair<std::string, std::shared_ptr<AclEntry>>> {
std::vector<std::pair<std::string, std::shared_ptr<AclEntry>>> entries;
for (const auto& mta : *policy.matchToAction()) {
auto a = aclByName.find(*mta.matcher());
if (a != aclByName.end()) {
auto aclCfg = *(a->second);
// We've already added any DENY acls
if (*aclCfg.actionType() == cfg::AclActionType::DENY) {
continue;
}
// Here is sending to regular port queue action
MatchAction matchAction = MatchAction();
if (auto sendToQueue = mta.action()->sendToQueue()) {
matchAction.setSendToQueue(std::make_pair(*sendToQueue, isCoppAcl));
}
if (auto actionCounter = mta.action()->counter()) {
auto counter = counterByName.find(*actionCounter);
if (counter == counterByName.end()) {
throw FbossError(
"Invalid config: No counter named ",
*mta.action()->counter(),
" found.");
}
matchAction.setTrafficCounter(*(counter->second));
}
if (auto setDscp = mta.action()->setDscp()) {
matchAction.setSetDscp(*setDscp);
}
if (auto ingressMirror = mta.action()->ingressMirror()) {
matchAction.setIngressMirror(*ingressMirror);
}
if (auto egressMirror = mta.action()->egressMirror()) {
matchAction.setEgressMirror(*egressMirror);
}
if (auto toCpuAction = mta.action()->toCpuAction()) {
matchAction.setToCpuAction(*toCpuAction);
}
if (auto redirectToNextHop = mta.action()->redirectToNextHop()) {
matchAction.setRedirectToNextHop(
std::make_pair(*redirectToNextHop, MatchAction::NextHopSet()));
}
auto acl = updateAcl(
aclStage,
aclCfg,
isCoppAcl ? cpuPriority++ : priority++,
&numExistingProcessed,
&changed,
tableName,
&matchAction);
if (acl->getAclAction().has_value()) {
const auto& inMirror = acl->getAclAction().value().getIngressMirror();
const auto& egMirror = acl->getAclAction().value().getIngressMirror();
if (inMirror.has_value() &&
!new_->getMirrors()->getMirrorIf(inMirror.value())) {
throw FbossError("Mirror ", inMirror.value(), " is undefined");
}
if (egMirror.has_value() &&
!new_->getMirrors()->getMirrorIf(egMirror.value())) {
throw FbossError("Mirror ", egMirror.value(), " is undefined");
}
}
entries.push_back(std::make_pair(acl->getID(), acl));
}
}
return entries;
};
// Add controlPlane traffic acls
if (cfg_->cpuTrafficPolicy() && cfg_->cpuTrafficPolicy()->trafficPolicy()) {
folly::gen::from(
addToAcls(*cfg_->cpuTrafficPolicy()->trafficPolicy(), true)) |
folly::gen::appendTo(newAcls);
}
// Add dataPlane traffic acls
if (auto dataPlaneTrafficPolicy = cfg_->dataPlaneTrafficPolicy()) {
folly::gen::from(addToAcls(*dataPlaneTrafficPolicy)) |
folly::gen::appendTo(newAcls);
}
if (FLAGS_enable_acl_table_group) {
if (orig_->getAclsForTable(aclStage, tableName.value()) &&
numExistingProcessed !=
orig_->getAclsForTable(aclStage, tableName.value())->size()) {
// Some existing ACLs were removed from the table (multiple acl tables
// implementation).
changed = true;
}
} else {
if (numExistingProcessed != orig_->getAcls()->size()) {
// Some existing ACLs were removed (single acl table implementation).
changed = true;
}
}
if (!changed) {
return nullptr;
}
if (tableName.has_value() &&
orig_->getAclsForTable(aclStage, tableName.value())) {
return orig_->getAclsForTable(aclStage, tableName.value())
->clone(std::move(newAcls));
}
return orig_->getAcls()->clone(std::move(newAcls));
}