in katran/lib/testing/BpfTester.cpp [140:261]
bool BpfTester::runBpfTesterFromFixtures(
int progFd,
std::unordered_map<int, std::string> retvalTranslation,
std::vector<void*> ctxs_in,
uint32_t ctx_size) {
if (ctxs_in.size() != 0) {
if (ctx_size == 0) {
LOG(INFO)
<< "size of single ctx value must be non zero if ctxs are specified";
return false;
}
if (ctxs_in.size() != config_.testData.size()) {
LOG(INFO) << "ctxs and input datasets must have equal number of elements";
return false;
}
}
uint32_t output_pckt_size{0};
uint32_t prog_ret_val{0};
uint64_t pckt_num{1};
std::string ret_val_str;
std::string test_result;
uint64_t packetsRoutedGlobalLruBefore{0};
uint64_t packetsRoutedGlobalLruAfter{0};
bool overallSuccess{true};
for (int i = 0; i < config_.testData.size(); i++) {
bool iterationSuccess = true;
if (config_.singleTestRunPacketNumber_ &&
*config_.singleTestRunPacketNumber_ != (i + 1)) {
++pckt_num;
VLOG(2) << "Skipped test for packet #" << i;
continue;
}
void* ctx_in = ctxs_in.size() != 0 ? ctxs_in[i] : nullptr;
auto pckt_buf = folly::IOBuf::create(kMaxXdpPcktSize);
auto input_pckt =
parser_.getPacketFromBase64(config_.testData[i].inputPacket);
writePcapOutput(input_pckt->cloneOne());
if (config_.testData[i].routedThroughGlobalLru) {
packetsRoutedGlobalLruBefore = getGlobalLruRoutedPackets();
}
auto res = adapter_.testXdpProg(
progFd,
kTestRepeatCount,
input_pckt->writableData(),
input_pckt->length(),
pckt_buf->writableData(),
&output_pckt_size,
&prog_ret_val,
nullptr, // duration
ctx_in,
ctx_size);
if (res < 0) {
LOG(INFO) << "failed to run bpf test on pckt #" << pckt_num << " errno "
<< errno << " : " << folly::errnoStr(errno);
++pckt_num;
overallSuccess = false;
continue;
}
if (config_.testData[i].routedThroughGlobalLru) {
packetsRoutedGlobalLruAfter = getGlobalLruRoutedPackets();
}
bool packetRoutedThroughGlobalLru =
((packetsRoutedGlobalLruAfter - packetsRoutedGlobalLruBefore) == 1);
auto ret_val_iter = retvalTranslation.find(prog_ret_val);
if (ret_val_iter == retvalTranslation.end()) {
ret_val_str = "UNKNOWN";
} else {
ret_val_str = ret_val_iter->second;
}
// adjust IOBuf so data data_end will acount for writen data
pckt_buf->append(output_pckt_size);
writePcapOutput(pckt_buf->cloneOne());
if (ret_val_str != config_.testData[i].expectedReturnValue) {
VLOG(2) << "value from test: " << ret_val_str
<< " expected: " << config_.testData[i].expectedReturnValue;
test_result = "\033[31mFailed\033[0m";
iterationSuccess = false;
}
if (iterationSuccess && config_.testData[i].routedThroughGlobalLru) {
if (*config_.testData[i].routedThroughGlobalLru &&
!packetRoutedThroughGlobalLru) {
VLOG(2)
<< "packet should have been routed through global lru, but wasn't";
test_result = "\033[31mFailed\033[0m";
iterationSuccess = false;
} else if (
!*config_.testData[i].routedThroughGlobalLru &&
packetRoutedThroughGlobalLru) {
VLOG(2)
<< "packet should not have been routed through global lru, but was";
test_result = "\033[31mFailed\033[0m";
iterationSuccess = false;
}
}
if (iterationSuccess) {
test_result = "\033[32mPassed\033[0m";
auto output_test_pckt =
parser_.convertPacketToBase64(std::move(pckt_buf));
if (output_test_pckt != config_.testData[i].expectedOutputPacket) {
VLOG(2) << "output packet not equal to expected one; expected pkt="
<< config_.testData[i].expectedOutputPacket
<< ", actual=" << output_test_pckt;
test_result = "\033[31mFailed\033[0m";
iterationSuccess = false;
}
}
overallSuccess = overallSuccess && iterationSuccess;
VLOG(2) << "pckt #" << pckt_num;
LOG(INFO) << folly::format(
"Test: {:60} result: {}", config_.testData[i].description, test_result);
++pckt_num;
}
return overallSuccess;
}