Skip to content

Commit

Permalink
Move the network hashes implementation from Bmv2 testgen to lib/ (#4526)
Browse files Browse the repository at this point in the history
* Move the network hashes implementation from Bmv2 testgen to lib/

* Add missing stream operator signature

* Apply suggestions from code review

Co-authored-by: Fabian Ruffy <5960321+fruffy@users.noreply.github.com>

* Update namespace to CamelCase

* Shuffle the file-level comments and license to make more sense

* Add basic CRC unit tests

* Generalize CRC calculation, avoid duplicates

* Polish the reflection function

* Fix format

* Fix crcCCITT

* Make constructor explicit

* Add comments on the checksums (mainly CRC)

* Add more tests, some from BMv2

* Add comments

---------

Co-authored-by: Fabian Ruffy <5960321+fruffy@users.noreply.github.com>
  • Loading branch information
vlstill and fruffy committed Mar 19, 2024
1 parent 4906dd7 commit 814ff5b
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ set(TESTGEN_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/cmd_stepper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/concolic.cpp
${CMAKE_CURRENT_SOURCE_DIR}/constants.cpp
${CMAKE_CURRENT_SOURCE_DIR}/contrib/bmv2_hash/calculations.cpp
${CMAKE_CURRENT_SOURCE_DIR}/expr_stepper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/map_direct_externs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/p4_asserts_parser.cpp
Expand Down
69 changes: 40 additions & 29 deletions backends/p4tools/modules/testgen/targets/bmv2/concolic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,28 @@
#include "ir/vector.h"
#include "lib/cstring.h"
#include "lib/exceptions.h"
#include "lib/nethash.h"

#include "backends/p4tools/modules/testgen/lib/concolic.h"
#include "backends/p4tools/modules/testgen/lib/exceptions.h"
#include "backends/p4tools/modules/testgen/lib/execution_state.h"
#include "backends/p4tools/modules/testgen/lib/packet_vars.h"
#include "backends/p4tools/modules/testgen/targets/bmv2/contrib/bmv2_hash/calculations.h"

namespace P4Tools::P4Testgen::Bmv2 {

big_int Bmv2Concolic::computeChecksum(const std::vector<const IR::Expression *> &exprList,
const Model &finalModel, int algo,
Model::ExpressionMap *resolvedExpressions) {
static big_int checksum(Bmv2HashAlgorithm algo, const uint8_t *buf, size_t len) {
// Pick a checksum according to the algorithm value.
ChecksumFunction checksumFun = nullptr;
switch (algo) {
case Bmv2HashAlgorithm::csum16: {
checksumFun = BMv2Hash::csum16;
break;
}
case Bmv2HashAlgorithm::crc32: {
checksumFun = BMv2Hash::crc32;
break;
}
case Bmv2HashAlgorithm::crc16: {
checksumFun = BMv2Hash::crc16;
break;
}
case Bmv2HashAlgorithm::identity: {
checksumFun = BMv2Hash::identity;
break;
}
case Bmv2HashAlgorithm::xor16: {
checksumFun = BMv2Hash::xor16;
break;
}
case Bmv2HashAlgorithm::csum16:
return NetHash::csum16(buf, len);
case Bmv2HashAlgorithm::crc32:
return NetHash::crc32(buf, len);
case Bmv2HashAlgorithm::crc16:
return NetHash::crc16(buf, len);
case Bmv2HashAlgorithm::identity:
return NetHash::identity(buf, len);
case Bmv2HashAlgorithm::xor16:
return NetHash::xor16(buf, len);
case Bmv2HashAlgorithm::random: {
BUG("Random should not be encountered here");
}
Expand All @@ -62,7 +49,11 @@ big_int Bmv2Concolic::computeChecksum(const std::vector<const IR::Expression *>
default:
TESTGEN_UNIMPLEMENTED("Algorithm %1% not implemented for hash.", algo);
}
}

big_int Bmv2Concolic::computeChecksum(const std::vector<const IR::Expression *> &exprList,
const Model &finalModel, Bmv2HashAlgorithm algo,
Model::ExpressionMap *resolvedExpressions) {
std::vector<uint8_t> bytes;
if (!exprList.empty()) {
const auto *concatExpr = exprList.at(0);
Expand All @@ -87,7 +78,7 @@ big_int Bmv2Concolic::computeChecksum(const std::vector<const IR::Expression *>
IR::getBigIntFromLiteral(finalModel.evaluate(concatExpr, true, resolvedExpressions));
bytes = convertBigIntToBytes(dataInt, concatWidth, true);
}
return checksumFun(bytes.data(), bytes.size());
return checksum(algo, bytes.data(), bytes.size());
}

const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{
Expand Down Expand Up @@ -118,7 +109,7 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{
checksumVar->node_type_name());
}
// Assign arguments to concrete variables and perform type checking.
auto algo = args->at(1)->expression->checkedTo<IR::Constant>()->asInt();
auto algo = Bmv2HashAlgorithm(args->at(1)->expression->checkedTo<IR::Constant>()->asInt());
Model::ExpressionMap resolvedExpressions;
const auto *base =
finalModel.evaluate(args->at(2)->expression, true, &resolvedExpressions);
Expand Down Expand Up @@ -179,7 +170,7 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{
// Assign arguments to concrete variables and perform type checking.
const auto *args = var->arguments;
const auto *checksumVar = args->at(0)->expression;
auto algo = args->at(1)->expression->checkedTo<IR::Constant>()->asInt();
auto algo = Bmv2HashAlgorithm(args->at(1)->expression->checkedTo<IR::Constant>()->asInt());
const auto *dataExpr = args->at(2)->expression;
const auto *checksumVarType = checksumVar->type;
// This is the maximum value this checksum can have.
Expand Down Expand Up @@ -227,7 +218,7 @@ const ConcolicMethodImpls::ImplList Bmv2Concolic::BMV2_CONCOLIC_METHOD_IMPLS{
// Assign arguments to concrete variables and perform type checking.
const auto *args = var->arguments;
const auto *checksumVar = args->at(0)->expression;
auto algo = args->at(1)->expression->checkedTo<IR::Constant>()->asInt();
auto algo = Bmv2HashAlgorithm(args->at(1)->expression->checkedTo<IR::Constant>()->asInt());
const auto *dataExpr = args->at(2)->expression;
const auto *checksumVarType = checksumVar->type;
Model::ExpressionMap resolvedExpressions;
Expand Down Expand Up @@ -278,4 +269,24 @@ const ConcolicMethodImpls::ImplList *Bmv2Concolic::getBmv2ConcolicMethodImpls()
return &BMV2_CONCOLIC_METHOD_IMPLS;
}

std::ostream &operator<<(std::ostream &os, Bmv2HashAlgorithm algo) {
#define ALGO_CASE(A) \
case Bmv2HashAlgorithm::A: \
return os << #A << " [" << int(algo) << "]"
switch (algo) {
ALGO_CASE(crc32);
ALGO_CASE(crc32_custom);
ALGO_CASE(crc16);
ALGO_CASE(crc16_custom);
ALGO_CASE(random);
ALGO_CASE(identity);
ALGO_CASE(csum16);
ALGO_CASE(xor16);
// No default: let the compiler produce a warning if some defined enum value is not covered.
}
#undef ALGO_CASE
// For values other then the declared ones.
return os << "INVALID [" << int(algo) << "]";
}

} // namespace P4Tools::P4Testgen::Bmv2
34 changes: 14 additions & 20 deletions backends/p4tools/modules/testgen/targets/bmv2/concolic.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,31 @@

namespace P4Tools::P4Testgen::Bmv2 {

enum class Bmv2HashAlgorithm {
crc32,
crc32_custom,
crc16,
crc16_custom,
random,
identity,
csum16,
xor16
};

std::ostream &operator<<(std::ostream &os, Bmv2HashAlgorithm algo);

class Bmv2Concolic : public Concolic {
private:
/// In the behavioral model, checksum functions have the following signature.
using ChecksumFunction = std::function<big_int(const uint8_t *buf, size_t len)>;

/// Chunk size is 8 bits, i.e., a byte.
static constexpr int CHUNK_SIZE = 8;

/// We are not using an enum class because we directly compare integers. This is because error
/// types are converted into integers in our interpreter. If we use an enum class, we have to
/// cast every enum access to int.
struct Bmv2HashAlgorithm {
using Type = enum {
crc32,
crc32_custom,
crc16,
crc16_custom,
random,
identity,
csum16,
xor16
};
};

/// This is the list of concolic functions that are implemented in this class.
static const ConcolicMethodImpls::ImplList BMV2_CONCOLIC_METHOD_IMPLS;

/// Call into a behavioral model helper function to compute the appropriate checksum. The
/// checksum is determined by @param algo.
static big_int computeChecksum(const std::vector<const IR::Expression *> &exprList,
const Model &finalModel, int algo,
const Model &finalModel, Bmv2HashAlgorithm algo,
Model::ExpressionMap *resolvedExpressions);

/// Compute a payload using the provided model and update the resolved concolic variables. Then
Expand Down

This file was deleted.

2 changes: 2 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ set (LIBP4CTOOLKIT_SRCS
json.cpp
log.cpp
match.cpp
nethash.cpp
nullstream.cpp
options.cpp
path.cpp
Expand Down Expand Up @@ -61,6 +62,7 @@ set (LIBP4CTOOLKIT_HDRS
gc.h
big_int_util.h
hash.h
nethash.h
hashvec.h
hex.h
hvec_map.h
Expand Down
Loading

0 comments on commit 814ff5b

Please sign in to comment.