void BcmAclEntry::createAclQualifiers()

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