void AclEntryFields::checkFollyDynamic()

in fboss/agent/state/AclEntry.cpp [432:548]


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