fboss/agent/state/AclEntry.cpp (584 lines of code) (raw):
/*
* Copyright (c) 2004-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include "fboss/agent/state/AclEntry.h"
#include <folly/Conv.h>
#include <folly/MacAddress.h>
#include <thrift/lib/cpp/util/EnumUtils.h>
#include "fboss/agent/gen-cpp2/switch_config_types.h"
#include "fboss/agent/state/AclMap.h"
#include "fboss/agent/state/NodeBase-defs.h"
#include "fboss/agent/state/StateUtils.h"
#include "fboss/agent/state/SwitchState.h"
#include "folly/IPAddress.h"
using apache::thrift::TEnumTraits;
using folly::IPAddress;
namespace {
constexpr auto kPriority = "priority";
constexpr auto kName = "name";
constexpr auto kActionType = "actionType";
constexpr auto kSrcIp = "srcIp";
constexpr auto kDstIp = "dstIp";
constexpr auto kL4SrcPort = "l4SrcPort";
constexpr auto kL4DstPort = "l4DstPort";
constexpr auto kProto = "proto";
constexpr auto kTcpFlagsBitMap = "tcpFlagsBitMap";
constexpr auto kSrcPort = "srcPort";
constexpr auto kDstPort = "dstPort";
constexpr auto kIpFrag = "ipFrag";
constexpr auto kIcmpCode = "icmpCode";
constexpr auto kIcmpType = "icmpType";
constexpr auto kDscp = "dscp";
constexpr auto kPortName = "portName";
constexpr auto kDstMac = "dstMac";
constexpr auto kIpType = "IpType";
constexpr auto kTtl = "ttl";
constexpr auto kTtlValue = "value";
constexpr auto kTtlMask = "mask";
constexpr auto kLookupClassL2 = "lookupClassL2";
constexpr auto kLookupClass = "lookupClass";
constexpr auto kLookupClassNeighbor = "lookupClassNeighbor";
constexpr auto kLookupClassRoute = "lookupClassRoute";
constexpr auto kPacketLookupResult = "packetLookupResult";
constexpr auto kVlanID = "vlanID";
constexpr auto kAclAction = "aclAction";
} // namespace
namespace facebook::fboss {
state::AclTtl AclTtl::toThrift() const {
auto aclTtl = state::AclTtl();
aclTtl.value() = value_;
aclTtl.mask() = mask_;
return aclTtl;
}
AclTtl AclTtl::fromThrift(state::AclTtl const& ttl) {
return AclTtl(ttl.get_value(), ttl.get_mask());
}
folly::dynamic AclTtl::toFollyDynamic() const {
folly::dynamic ttl = folly::dynamic::object;
ttl[kTtlValue] = static_cast<uint16_t>(value_);
ttl[kTtlMask] = static_cast<uint16_t>(mask_);
return ttl;
}
AclTtl AclTtl::fromFollyDynamic(const folly::dynamic& ttlJson) {
if (ttlJson.find(kTtlValue) == ttlJson.items().end()) {
throw FbossError("ttl should have a value set");
}
if (ttlJson.find(kTtlMask) == ttlJson.items().end()) {
throw FbossError("ttl should have a mask set");
}
return AclTtl(ttlJson[kTtlValue].asInt(), ttlJson[kTtlMask].asInt());
}
state::AclEntryFields AclEntryFields::toThrift() const {
auto entry = state::AclEntryFields();
entry.priority() = priority;
entry.name() = name;
if (srcIp.first) {
entry.srcIp() = IPAddress::networkToString(srcIp);
}
if (dstIp.first) {
entry.dstIp() = IPAddress::networkToString(dstIp);
}
entry.proto().from_optional(proto);
entry.tcpFlagsBitMap().from_optional(tcpFlagsBitMap);
entry.srcPort().from_optional(srcPort);
entry.dstPort().from_optional(dstPort);
entry.ipFrag().from_optional(ipFrag);
entry.proto().from_optional(proto);
entry.proto().from_optional(proto);
if (ttl.has_value()) {
entry.ttl() = ttl->toThrift();
}
entry.icmpType().from_optional(icmpType);
entry.icmpCode().from_optional(icmpCode);
entry.dscp().from_optional(dscp);
entry.ipType().from_optional(ipType);
if (dstMac.has_value()) {
entry.dstMac() = dstMac->toString();
}
entry.l4SrcPort().from_optional(l4SrcPort);
entry.l4DstPort().from_optional(l4DstPort);
entry.lookupClassL2().from_optional(lookupClassL2);
entry.lookupClass().from_optional(lookupClass);
entry.lookupClassNeighbor().from_optional(lookupClassNeighbor);
entry.lookupClassRoute().from_optional(lookupClassRoute);
entry.packetLookupResult().from_optional(packetLookupResult);
entry.vlanID().from_optional(vlanID);
entry.etherType().from_optional(etherType);
entry.actionType() = actionType;
if (aclAction.has_value()) {
entry.aclAction() = aclAction->toThrift();
}
return entry;
}
AclEntryFields AclEntryFields::fromThrift(state::AclEntryFields const& entry) {
auto aclEntryFields = AclEntryFields(entry.get_priority(), entry.get_name());
if (auto srcIp = entry.srcIp()) {
aclEntryFields.srcIp = IPAddress::createNetwork(*srcIp);
}
if (auto dstIp = entry.dstIp()) {
aclEntryFields.dstIp = IPAddress::createNetwork(*dstIp);
}
if (aclEntryFields.srcIp.first && aclEntryFields.dstIp.first &&
aclEntryFields.srcIp.first.isV4() != aclEntryFields.dstIp.first.isV4()) {
throw FbossError(
"Unmatched ACL IP versions ",
aclEntryFields.srcIp.first,
" vs ",
aclEntryFields.dstIp.first);
}
aclEntryFields.proto = entry.proto().to_optional();
aclEntryFields.tcpFlagsBitMap = entry.tcpFlagsBitMap().to_optional();
aclEntryFields.srcPort = entry.srcPort().to_optional();
aclEntryFields.dstPort = entry.dstPort().to_optional();
aclEntryFields.ipFrag = entry.ipFrag().to_optional();
aclEntryFields.proto = entry.proto().to_optional();
aclEntryFields.proto = entry.proto().to_optional();
if (auto ttl = entry.ttl()) {
aclEntryFields.ttl = AclTtl::fromThrift(*ttl);
}
aclEntryFields.icmpType = entry.icmpType().to_optional();
aclEntryFields.icmpCode = entry.icmpCode().to_optional();
aclEntryFields.dscp = entry.dscp().to_optional();
aclEntryFields.ipType = entry.ipType().to_optional();
if (auto dstMac = entry.dstMac()) {
aclEntryFields.dstMac = folly::MacAddress(*dstMac);
}
aclEntryFields.l4SrcPort = entry.l4SrcPort().to_optional();
aclEntryFields.l4DstPort = entry.l4DstPort().to_optional();
aclEntryFields.lookupClassL2 = entry.lookupClassL2().to_optional();
aclEntryFields.lookupClass = entry.lookupClass().to_optional();
aclEntryFields.lookupClassNeighbor =
entry.lookupClassNeighbor().to_optional();
aclEntryFields.lookupClassRoute = entry.lookupClassRoute().to_optional();
aclEntryFields.packetLookupResult = entry.packetLookupResult().to_optional();
aclEntryFields.vlanID = entry.vlanID().to_optional();
aclEntryFields.etherType = entry.etherType().to_optional();
aclEntryFields.actionType = entry.get_actionType();
if (auto aclAction = entry.aclAction()) {
aclEntryFields.aclAction = MatchAction::fromThrift(*aclAction);
}
return aclEntryFields;
}
// TODO: remove all migration along with old ser/des after next disruptive push
folly::dynamic AclEntryFields::migrateToThrifty(const folly::dynamic& dyn) {
folly::dynamic newDyn = dyn;
// rename IpType -> ipType just for thrift name convention
ThriftyUtils::renameField(newDyn, kIpType, "ipType");
ThriftyUtils::changeEnumToInt<cfg::IpFragMatch>(newDyn, kIpFrag);
ThriftyUtils::changeEnumToInt<cfg::AclLookupClass>(newDyn, kLookupClassL2);
ThriftyUtils::changeEnumToInt<cfg::AclLookupClass>(newDyn, kLookupClass);
ThriftyUtils::changeEnumToInt<cfg::AclLookupClass>(
newDyn, kLookupClassNeighbor);
ThriftyUtils::changeEnumToInt<cfg::AclLookupClass>(newDyn, kLookupClassRoute);
ThriftyUtils::changeEnumToInt<cfg::AclActionType>(newDyn, kActionType);
if (auto it = newDyn.find(kAclAction); it != newDyn.items().end()) {
it->second = MatchAction::migrateToThrifty(it->second);
}
return newDyn;
}
void AclEntryFields::migrateFromThrifty(folly::dynamic& dyn) {
ThriftyUtils::renameField(dyn, "ipType", kIpType);
ThriftyUtils::changeEnumToString<cfg::IpFragMatch>(dyn, kIpFrag);
ThriftyUtils::changeEnumToString<cfg::AclLookupClass>(dyn, kLookupClassL2);
ThriftyUtils::changeEnumToString<cfg::AclLookupClass>(dyn, kLookupClass);
ThriftyUtils::changeEnumToString<cfg::AclLookupClass>(
dyn, kLookupClassNeighbor);
ThriftyUtils::changeEnumToString<cfg::AclLookupClass>(dyn, kLookupClassRoute);
ThriftyUtils::changeEnumToString<cfg::AclActionType>(dyn, kActionType);
if (auto it = dyn.find(kAclAction); it != dyn.items().end()) {
MatchAction::migrateFromThrifty(it->second);
}
}
folly::dynamic AclEntryFields::toFollyDynamicLegacy() const {
folly::dynamic aclEntry = folly::dynamic::object;
if (srcIp.first) {
aclEntry[kSrcIp] = IPAddress::networkToString(srcIp);
}
if (dstIp.first) {
aclEntry[kDstIp] = IPAddress::networkToString(dstIp);
}
if (dstMac) {
aclEntry[kDstMac] = dstMac->toString();
}
if (proto) {
aclEntry[kProto] = static_cast<uint8_t>(proto.value());
}
if (tcpFlagsBitMap) {
aclEntry[kTcpFlagsBitMap] = static_cast<uint8_t>(tcpFlagsBitMap.value());
}
if (srcPort) {
aclEntry[kSrcPort] = static_cast<uint16_t>(srcPort.value());
}
if (dstPort) {
aclEntry[kDstPort] = static_cast<uint16_t>(dstPort.value());
}
if (ipFrag) {
auto ipFragName = apache::thrift::util::enumName(*ipFrag);
if (ipFragName == nullptr) {
throw FbossError("invalid ipFrag");
}
aclEntry[kIpFrag] = ipFragName;
}
if (icmpCode) {
aclEntry[kIcmpCode] = static_cast<uint8_t>(icmpCode.value());
}
if (icmpType) {
aclEntry[kIcmpType] = static_cast<uint8_t>(icmpType.value());
}
if (dscp) {
aclEntry[kDscp] = static_cast<uint8_t>(dscp.value());
}
if (ipType) {
aclEntry[kIpType] = static_cast<uint16_t>(ipType.value());
}
if (ttl) {
aclEntry[kTtl] = ttl.value().toFollyDynamic();
}
if (l4SrcPort) {
aclEntry[kL4SrcPort] = static_cast<uint16_t>(l4SrcPort.value());
}
if (l4DstPort) {
aclEntry[kL4DstPort] = static_cast<uint16_t>(l4DstPort.value());
}
if (lookupClassL2) {
auto lookupClassNameL2 = apache::thrift::util::enumName(*lookupClassL2);
if (lookupClassNameL2 == nullptr) {
throw FbossError("invalid lookupClassL2");
}
aclEntry[kLookupClassL2] = lookupClassNameL2;
}
if (lookupClass) {
auto lookupClassName = apache::thrift::util::enumName(*lookupClass);
if (lookupClassName == nullptr) {
throw FbossError("invalid lookupClass");
}
aclEntry[kLookupClass] = lookupClassName;
}
if (lookupClassNeighbor) {
auto lookupClassNameNeighbor =
apache::thrift::util::enumName(*lookupClassNeighbor);
if (lookupClassNameNeighbor == nullptr) {
throw FbossError("invalid lookupClassNeighbor");
}
aclEntry[kLookupClassNeighbor] = lookupClassNameNeighbor;
}
if (lookupClassRoute) {
auto lookupClassNameRoute =
apache::thrift::util::enumName(*lookupClassRoute);
if (lookupClassNameRoute == nullptr) {
throw FbossError("invalid lookupClassRoute");
}
aclEntry[kLookupClassRoute] = lookupClassNameRoute;
}
if (packetLookupResult) {
aclEntry[kPacketLookupResult] =
static_cast<uint32_t>(packetLookupResult.value());
}
if (vlanID) {
aclEntry[kVlanID] = static_cast<uint32_t>(vlanID.value());
}
auto actionTypeName = apache::thrift::util::enumName(actionType);
if (actionTypeName == nullptr) {
throw FbossError("invalid actionType");
}
aclEntry[kActionType] = actionTypeName;
if (aclAction) {
aclEntry[kAclAction] = aclAction.value().toFollyDynamic();
}
aclEntry[kPriority] = priority;
aclEntry[kName] = name;
return aclEntry;
}
AclEntryFields AclEntryFields::fromFollyDynamicLegacy(
const folly::dynamic& aclEntryJson) {
AclEntryFields aclEntry(
aclEntryJson[kPriority].asInt(), aclEntryJson[kName].asString());
if (aclEntryJson.find(kSrcIp) != aclEntryJson.items().end()) {
aclEntry.srcIp = IPAddress::createNetwork(aclEntryJson[kSrcIp].asString());
}
if (aclEntryJson.find(kDstIp) != aclEntryJson.items().end()) {
aclEntry.dstIp = IPAddress::createNetwork(aclEntryJson[kDstIp].asString());
}
if (aclEntry.srcIp.first && aclEntry.dstIp.first &&
aclEntry.srcIp.first.isV4() != aclEntry.dstIp.first.isV4()) {
throw FbossError(
"Unmatched ACL IP versions ",
aclEntryJson[kSrcIp].asString(),
" vs ",
aclEntryJson[kDstIp].asString());
}
if (aclEntryJson.find(kDstMac) != aclEntryJson.items().end()) {
aclEntry.dstMac = folly::MacAddress(aclEntryJson[kDstMac].asString());
}
if (aclEntryJson.find(kProto) != aclEntryJson.items().end()) {
aclEntry.proto = aclEntryJson[kProto].asInt();
}
if (aclEntryJson.find(kTcpFlagsBitMap) != aclEntryJson.items().end()) {
aclEntry.tcpFlagsBitMap = aclEntryJson[kTcpFlagsBitMap].asInt();
}
if (aclEntryJson.find(kSrcPort) != aclEntryJson.items().end()) {
aclEntry.srcPort = aclEntryJson[kSrcPort].asInt();
}
if (aclEntryJson.find(kDstPort) != aclEntryJson.items().end()) {
aclEntry.dstPort = aclEntryJson[kDstPort].asInt();
}
if (aclEntryJson.find(kL4SrcPort) != aclEntryJson.items().end()) {
aclEntry.l4SrcPort = aclEntryJson[kL4SrcPort].asInt();
}
if (aclEntryJson.find(kL4DstPort) != aclEntryJson.items().end()) {
aclEntry.l4DstPort = aclEntryJson[kL4DstPort].asInt();
}
if (aclEntryJson.find(kIpFrag) != aclEntryJson.items().end()) {
cfg::IpFragMatch ipFrag;
TEnumTraits<cfg::IpFragMatch>::findValue(
aclEntryJson[kIpFrag].asString().c_str(), &ipFrag);
aclEntry.ipFrag = ipFrag;
}
if (aclEntryJson.find(kIcmpType) != aclEntryJson.items().end()) {
aclEntry.icmpType = aclEntryJson[kIcmpType].asInt();
}
if (aclEntryJson.find(kIcmpCode) != aclEntryJson.items().end()) {
aclEntry.icmpCode = aclEntryJson[kIcmpCode].asInt();
}
if (aclEntryJson.find(kDscp) != aclEntryJson.items().end()) {
aclEntry.dscp = aclEntryJson[kDscp].asInt();
}
if (aclEntryJson.find(kIpType) != aclEntryJson.items().end()) {
aclEntry.ipType = static_cast<cfg::IpType>(aclEntryJson[kIpType].asInt());
}
if (aclEntryJson.find(kTtl) != aclEntryJson.items().end()) {
aclEntry.ttl = AclTtl::fromFollyDynamic(aclEntryJson[kTtl]);
}
if (aclEntryJson.find(kLookupClassL2) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassL2;
TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassL2].asString().c_str(), &lookupClassL2);
aclEntry.lookupClassL2 = lookupClassL2;
}
if (aclEntryJson.find(kLookupClass) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClass;
TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClass].asString().c_str(), &lookupClass);
aclEntry.lookupClass = lookupClass;
}
if (aclEntryJson.find(kLookupClassNeighbor) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassNeighbor;
TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassNeighbor].asString().c_str(),
&lookupClassNeighbor);
aclEntry.lookupClassNeighbor = lookupClassNeighbor;
}
if (aclEntryJson.find(kLookupClassRoute) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassRoute;
TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassRoute].asString().c_str(), &lookupClassRoute);
aclEntry.lookupClassRoute = lookupClassRoute;
}
if (aclEntryJson.find(kPacketLookupResult) != aclEntryJson.items().end()) {
aclEntry.packetLookupResult = static_cast<cfg::PacketLookupResultType>(
aclEntryJson[kPacketLookupResult].asInt());
}
if (aclEntryJson.find(kVlanID) != aclEntryJson.items().end()) {
aclEntry.vlanID = aclEntryJson[kVlanID].asInt();
}
TEnumTraits<cfg::AclActionType>::findValue(
aclEntryJson[kActionType].asString().c_str(), &aclEntry.actionType);
if (aclEntryJson.find(kAclAction) != aclEntryJson.items().end()) {
aclEntry.aclAction =
MatchAction::fromFollyDynamic(aclEntryJson[kAclAction]);
}
return aclEntry;
}
void AclEntryFields::checkFollyDynamic(const folly::dynamic& aclEntryJson) {
// check src ip and dst ip are of the same type
if (aclEntryJson.find(kSrcIp) != aclEntryJson.items().end() &&
aclEntryJson.find(kDstIp) != aclEntryJson.items().end()) {
auto src = IPAddress::createNetwork(aclEntryJson[kSrcIp].asString());
auto dst = IPAddress::createNetwork(aclEntryJson[kDstIp].asString());
if (src.first.isV4() != dst.first.isV4()) {
throw FbossError(
"Unmatched ACL IP versions ",
aclEntryJson[kSrcIp].asString(),
" vs ",
aclEntryJson[kDstIp].asString(),
"; source and destination IPs must be of the same type");
}
}
// check lookupClass is valid
if (aclEntryJson.find(kLookupClass) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClass;
if (!TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClass].asString().c_str(), &lookupClass)) {
throw FbossError(
"Unsupported ACL Lookup Class option ",
aclEntryJson[kLookupClass].asString());
}
}
// check lookupClassL2 is valid
if (aclEntryJson.find(kLookupClassL2) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassL2;
if (!TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassL2].asString().c_str(), &lookupClassL2)) {
throw FbossError(
"Unsupported ACL Lookup ClassL2 option ",
aclEntryJson[kLookupClassL2].asString());
}
}
// check lookupClassNeighbor is valid
if (aclEntryJson.find(kLookupClassNeighbor) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassNeighbor;
if (!TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassNeighbor].asString().c_str(),
&lookupClassNeighbor)) {
throw FbossError(
"Unsupported ACL LookupClassNeighbor option ",
aclEntryJson[kLookupClassNeighbor].asString());
}
}
// check lookupClassRoute is valid
if (aclEntryJson.find(kLookupClassRoute) != aclEntryJson.items().end()) {
cfg::AclLookupClass lookupClassRoute;
if (!TEnumTraits<cfg::AclLookupClass>::findValue(
aclEntryJson[kLookupClassRoute].asString().c_str(),
&lookupClassRoute)) {
throw FbossError(
"Unsupported ACL LookupClassRoute option ",
aclEntryJson[kLookupClassRoute].asString());
}
}
// check ipFrag is valid
if (aclEntryJson.find(kIpFrag) != aclEntryJson.items().end()) {
cfg::IpFragMatch ipFrag;
if (!TEnumTraits<cfg::IpFragMatch>::findValue(
aclEntryJson[kIpFrag].asString().c_str(), &ipFrag)) {
throw FbossError(
"Unsupported ACL IP fragmentation option ",
aclEntryJson[kIpFrag].asString());
}
}
// check action is valid
cfg::AclActionType aclActionType;
if (!TEnumTraits<cfg::AclActionType>::findValue(
aclEntryJson[kActionType].asString().c_str(), &aclActionType)) {
throw FbossError(
"Unsupported ACL action ", aclEntryJson[kActionType].asString());
}
// check icmp type exists when icmp code exist
if (aclEntryJson.find(kIcmpCode) != aclEntryJson.items().end() &&
aclEntryJson.find(kIcmpType) == aclEntryJson.items().end()) {
throw FbossError("icmp type must be set when icmp code is set");
}
// the value of icmp type must be 0~255
if (aclEntryJson.find(kIcmpType) != aclEntryJson.items().end() &&
(aclEntryJson[kIcmpType].asInt() < 0 ||
aclEntryJson[kIcmpType].asInt() > kMaxIcmpType)) {
throw FbossError(
"icmp type value must be between 0 and ", std::to_string(kMaxIcmpType));
}
// the value of icmp code must be 0~255
if (aclEntryJson.find(kIcmpCode) != aclEntryJson.items().end() &&
(aclEntryJson[kIcmpCode].asInt() < 0 ||
aclEntryJson[kIcmpCode].asInt() > kMaxIcmpCode)) {
throw FbossError(
"icmp code value must be between 0 and ", std::to_string(kMaxIcmpCode));
}
// check the "proto" is either "icmp" or "icmpv6" when icmptype is set
if (aclEntryJson.find(kIcmpType) != aclEntryJson.items().end() &&
(aclEntryJson.find(kProto) == aclEntryJson.items().end() ||
!(aclEntryJson[kProto] == kProtoIcmp ||
aclEntryJson[kProto] == kProtoIcmpv6))) {
throw FbossError(
"proto must be either icmp or icmpv6 ", "if icmp type is set");
}
if (aclEntryJson.find(kL4SrcPort) != aclEntryJson.items().end() &&
(aclEntryJson[kL4SrcPort].asInt() < 0 ||
aclEntryJson[kL4SrcPort].asInt() > kMaxL4Port)) {
throw FbossError(
"L4 source port must be between 0 and ", std::to_string(kMaxL4Port));
}
if (aclEntryJson.find(kL4DstPort) != aclEntryJson.items().end() &&
(aclEntryJson[kL4DstPort].asInt() < 0 ||
aclEntryJson[kL4DstPort].asInt() > kMaxL4Port)) {
throw FbossError(
"L4 destination port must be between 0 and ",
std::to_string(kMaxL4Port));
}
}
std::set<cfg::AclTableQualifier> AclEntry::getRequiredAclTableQualifiers()
const {
std::set<cfg::AclTableQualifier> qualifiers{};
auto setIpQualifier = [&qualifiers](
auto cidr, auto v4Qualifier, auto v6Qualifier) {
if (cidr == folly::CIDRNetwork(folly::IPAddress(), 0)) {
return;
}
if (cidr.first.isV4()) {
qualifiers.insert(v4Qualifier);
} else {
qualifiers.insert(v6Qualifier);
}
};
setIpQualifier(
getSrcIp(),
cfg::AclTableQualifier::SRC_IPV4,
cfg::AclTableQualifier::SRC_IPV6);
setIpQualifier(
getDstIp(),
cfg::AclTableQualifier::DST_IPV4,
cfg::AclTableQualifier::DST_IPV6);
if (getProto()) {
qualifiers.insert(cfg::AclTableQualifier::IP_PROTOCOL);
}
if (getTcpFlagsBitMap()) {
qualifiers.insert(cfg::AclTableQualifier::TCP_FLAGS);
}
if (getSrcPort()) {
qualifiers.insert(cfg::AclTableQualifier::SRC_PORT);
}
if (getDstPort()) {
qualifiers.insert(cfg::AclTableQualifier::OUT_PORT);
}
if (getIpFrag()) {
qualifiers.insert(cfg::AclTableQualifier::IP_FRAG);
}
if (getIcmpType() && getProto()) {
auto proto = getProto().value();
if (proto == 1) {
qualifiers.insert(cfg::AclTableQualifier::ICMPV4_TYPE);
} else {
qualifiers.insert(cfg::AclTableQualifier::ICMPV6_TYPE);
}
}
if (getDscp()) {
qualifiers.insert(cfg::AclTableQualifier::DSCP);
}
if (getIpType()) {
qualifiers.insert(cfg::AclTableQualifier::IP_TYPE);
}
if (getTtl()) {
qualifiers.insert(cfg::AclTableQualifier::TTL);
}
if (getDstMac()) {
qualifiers.insert(cfg::AclTableQualifier::DST_MAC);
}
if (getL4SrcPort()) {
qualifiers.insert(cfg::AclTableQualifier::L4_SRC_PORT);
}
if (getL4DstPort()) {
qualifiers.insert(cfg::AclTableQualifier::L4_DST_PORT);
}
if (getLookupClassL2()) {
qualifiers.insert(cfg::AclTableQualifier::LOOKUP_CLASS_L2);
}
if (getLookupClassNeighbor()) {
qualifiers.insert(cfg::AclTableQualifier::LOOKUP_CLASS_NEIGHBOR);
}
if (getLookupClassRoute()) {
qualifiers.insert(cfg::AclTableQualifier::LOOKUP_CLASS_ROUTE);
}
if (getPacketLookupResult()) {
// TODO: add qualifier in AclTableQualifier enum
}
if (getEtherType()) {
qualifiers.insert(cfg::AclTableQualifier::ETHER_TYPE);
}
return qualifiers;
}
AclEntry* AclEntry::modify(std::shared_ptr<SwitchState>* state) {
if (!isPublished()) {
CHECK(!(*state)->isPublished());
return this;
}
AclMap* acls = (*state)->getAcls()->modify(state);
auto newEntry = clone();
auto* ptr = newEntry.get();
acls->updateNode(std::move(newEntry));
return ptr;
}
AclEntry::AclEntry(int priority, const std::string& name)
: ThriftyBaseT(priority, name) {}
template class ThriftyBaseT<state::AclEntryFields, AclEntry, AclEntryFields>;
} // namespace facebook::fboss