in fboss/agent/hw/bcm/BcmAclEntry.cpp [122:294]
void BcmAclEntry::createAclQualifiers() {
int rv;
// One or both IP addresses can be empty
auto isV4 = (acl_->getSrcIp().first && acl_->getSrcIp().first.isV4()) ||
(acl_->getDstIp().first && acl_->getDstIp().first.isV4());
auto isV6 = (acl_->getSrcIp().first && acl_->getSrcIp().first.isV6()) ||
(acl_->getDstIp().first && acl_->getDstIp().first.isV6());
// Bcm ContentAware processing engine use the same field for both V4 and V6.
// For a V4 packet, the lower 32 bit is the V4 address, with all other
// (128 - 32) bits set to 0.
if (isV4) {
qualifyIpAddresses<IPAddressV4>(acl_, hw_->getUnit(), handle_);
} else if (isV6) {
qualifyIpAddresses<IPAddressV6>(acl_, hw_->getUnit(), handle_);
}
if (acl_->getProto()) {
rv = bcm_field_qualify_IpProtocol(
hw_->getUnit(), handle_, acl_->getProto().value(), 0xFF);
bcmCheckError(rv, "failed to add IP protocol field");
}
if (acl_->getL4SrcPort()) {
rv = bcm_field_qualify_L4SrcPort(
hw_->getUnit(), handle_, acl_->getL4SrcPort().value(), 0xFFFF);
bcmCheckError(rv, "failed to add L4 Src Port field");
}
if (acl_->getL4DstPort()) {
rv = bcm_field_qualify_L4DstPort(
hw_->getUnit(), handle_, acl_->getL4DstPort().value(), 0xFFFF);
bcmCheckError(rv, "failed to add L4 Dst Port field");
}
if (acl_->getTcpFlagsBitMap()) {
rv = bcm_field_qualify_TcpControl(
hw_->getUnit(), handle_, acl_->getTcpFlagsBitMap().value(), 0xFF);
bcmCheckError(rv, "failed to add TCP flags field");
}
if (acl_->getSrcPort()) {
rv = bcm_field_qualify_SrcPort(
hw_->getUnit(),
handle_,
0x0,
0xFF, // checked with bcm, both port and module mask value should not
// be bigger than 0xFF
acl_->getSrcPort().value(),
0xFF);
bcmCheckError(rv, "failed to add physical Src Port field");
}
if (acl_->getDstPort()) {
rv = bcm_field_qualify_DstPort(
hw_->getUnit(),
handle_,
0x0,
0xFF, // checked with bcm, both port and module mask value should not
// be bigger than 0xFF
acl_->getDstPort().value(),
0xFF);
bcmCheckError(rv, "failed to add physical Dst Port field");
}
bcm_mac_t macMask;
macToBcm(MacAddress::BROADCAST, &macMask);
if (acl_->getDstMac()) {
bcm_mac_t dstMac;
macToBcm(acl_->getDstMac().value(), &dstMac);
rv = bcm_field_qualify_DstMac(hw_->getUnit(), handle_, dstMac, macMask);
bcmCheckError(rv, "failed to add Dst Mac field");
}
if (acl_->getIpFrag()) {
bcm_field_IpFrag_t ipFragOpt =
cfgIpFragToBcmIpFrag(acl_->getIpFrag().value());
rv = bcm_field_qualify_IpFrag(hw_->getUnit(), handle_, ipFragOpt);
bcmCheckError(rv, "failed to qualify a ip frag option");
}
if (acl_->getIcmpType()) {
uint16_t typeCode, typeCodeMask;
cfgIcmpTypeCodeToBcmIcmpCodeMask(
acl_->getIcmpType(), acl_->getIcmpCode(), &typeCode, &typeCodeMask);
// BRCM is reusing L4SrcPort for icmp
rv = bcm_field_qualify_L4SrcPort(
hw_->getUnit(), handle_, typeCode, typeCodeMask);
bcmCheckError(rv, "failed to qualify icmp type code");
}
if (acl_->getDscp()) {
uint8 bcmData, bcmMask;
cfgDscpToBcmDscp(acl_->getDscp().value(), &bcmData, &bcmMask);
rv = bcm_field_qualify_DSCP(hw_->getUnit(), handle_, bcmData, bcmMask);
bcmCheckError(rv, "failed to qualify on DSCP");
}
if (acl_->getIpType()) {
bcm_field_IpType_t ipType = cfgIpTypeToBcmIpType(acl_->getIpType().value());
rv = bcm_field_qualify_IpType(hw_->getUnit(), handle_, ipType);
bcmCheckError(rv, "failed to qualify IP type");
}
if (acl_->getEtherType()) {
uint16_t bcmData, bcmMask;
bcmData = static_cast<uint16>(acl_->getEtherType().value());
bcmMask = 0xFFFF;
rv = bcm_field_qualify_EtherType(hw_->getUnit(), handle_, bcmData, bcmMask);
bcmCheckError(rv, "failed to qualify Ether type");
}
if (acl_->getTtl()) {
rv = bcm_field_qualify_Ttl(
hw_->getUnit(),
handle_,
acl_->getTtl().value().getValue(),
acl_->getTtl().value().getMask());
bcmCheckError(rv, "failed to qualify TTL");
}
/*
* lookupClassNeighbor and lookupClassRoute are both represented by
* DstClassL3.
*/
if (acl_->getLookupClassNeighbor()) {
auto lookupClassNeighbor = acl_->getLookupClassNeighbor().value();
if (BcmClassIDUtil::isValidLookupClass(lookupClassNeighbor)) {
auto classId = static_cast<int>(lookupClassNeighbor);
rv = bcm_field_qualify_DstClassL3(
hw_->getUnit(), handle_, classId, 0xFFFFFFFF);
bcmCheckError(rv, "failed to qualify DstClassL3:", classId);
} else {
throw FbossError(
"Unrecognized acl lookupClassNeighbor ",
apache::thrift::util::enumNameSafe(lookupClassNeighbor));
}
}
if (acl_->getLookupClassRoute()) {
auto lookupClassRoute = acl_->getLookupClassRoute().value();
if (BcmClassIDUtil::isValidLookupClass(lookupClassRoute)) {
auto classId = static_cast<int>(lookupClassRoute);
rv = bcm_field_qualify_DstClassL3(
hw_->getUnit(), handle_, classId, 0xFFFFFFFF);
bcmCheckError(rv, "failed to qualify DstClassL3:", classId);
} else {
throw FbossError(
"Unrecognized acl lookupClassRoute ",
apache::thrift::util::enumNameSafe(lookupClassRoute));
}
}
if (acl_->getLookupClassL2()) {
auto lookupClassL2 = acl_->getLookupClassL2().value();
auto classId = static_cast<int>(lookupClassL2);
rv = bcm_field_qualify_DstClassL2(
hw_->getUnit(), handle_, classId, 0xFFFFFFFF);
bcmCheckError(rv, "failed to qualify DstClassL2:", classId);
}
if (acl_->getPacketLookupResult()) {
auto packetLookupResultValue = acl_->getPacketLookupResult().value();
auto packetLookupResult =
cfgPacketLookupResultToBcmPktResult(packetLookupResultValue);
rv = bcm_field_qualify_PacketRes(
hw_->getUnit(), handle_, packetLookupResult, 0xFFFFFFFF);
bcmCheckError(
rv, "failed to qualify PacketLookupResult:", packetLookupResult);
}
if (acl_->getVlanID()) {
rv = bcm_field_qualify_OuterVlanId(
hw_->getUnit(), handle_, acl_->getVlanID().value(), 0xFFF);
bcmCheckError(
rv, "failed to qualify OuterVlanId:", acl_->getVlanID().value());
}
}