std::shared_ptr ThriftConfigApplier::updateAcls()

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