Skip to content

Commit fe0124f

Browse files
authored
Add DPDK tests (#2106)
1 parent e9e3cf4 commit fe0124f

11 files changed

Lines changed: 128 additions & 70 deletions

File tree

.github/workflows/build_and_test.yml

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -312,71 +312,98 @@ jobs:
312312
key: ${{ steps.ccache-restore.outputs.cache-primary-key }}
313313

314314
dpdk:
315-
runs-on: ubuntu-latest
316-
container: seladb/${{ matrix.image }}
315+
runs-on: ubuntu-24.04
317316
strategy:
318317
matrix:
319318
include:
320-
- image: ubuntu2404-dpdk2411
321-
- image: ubuntu2404-dpdk2311
322-
- image: ubuntu2204-dpdk2211
323-
319+
- dpdk_version: 24.11.5
320+
- dpdk_version: 23.11.6
324321
steps:
325-
- name: Check AVX-512 support
326-
run: |
327-
echo "::debug::$(grep flags /proc/cpuinfo)"
328-
if grep -q avx512 /proc/cpuinfo; then
329-
echo "avx512=true" >> $GITHUB_ENV
330-
else
331-
echo "avx512=false" >> $GITHUB_ENV
332-
fi
333-
334322
- name: Checkout code
335323
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
336324

337-
- name: Restore Ccache
338-
id: ccache-restore
325+
- name: Install dependencies
326+
run: |
327+
sudo apt update && sudo apt -y install meson libnuma-dev libpcap-dev tcpreplay
328+
pip install --break-system-packages pyelftools
329+
330+
- name: Restore DPDK cache
331+
id: cache-dpdk
339332
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
340333
with:
341-
path: ${{ env.CCACHE_DIR }}
342-
key: ${{ matrix.image }}-ccache-${{ github.run_id }}
343-
restore-keys: |
344-
${{ matrix.image }}-ccache
334+
path: dpdk/install
335+
key: dpdk-${{ runner.os }}-${{ matrix.dpdk_version }}
336+
337+
- name: Install DPDK
338+
if: steps.cache-dpdk.outputs.cache-hit != 'true'
339+
run: |
340+
wget https://fast.dpdk.org/rel/dpdk-${{ matrix.dpdk_version }}.tar.xz \
341+
&& tar -xvf dpdk-${{ matrix.dpdk_version }}.tar.xz \
342+
&& rm -rf dpdk-${{ matrix.dpdk_version }}.tar.xz \
343+
&& mv dpdk-stable-${{ matrix.dpdk_version }} dpdk && cd dpdk \
344+
&& meson setup build --prefix=${{ github.workspace }}/dpdk/install \
345+
&& ninja -C build \
346+
&& ninja -C build install
347+
348+
- name: Cache DPDK
349+
if: steps.cache-dpdk.outputs.cache-hit != 'true'
350+
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
351+
with:
352+
path: dpdk/install
353+
key: dpdk-${{ runner.os }}-${{ matrix.dpdk_version }}
345354

346355
- name: Configure PcapPlusPlus
347-
run: cmake -DPCAPPP_USE_DPDK=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR"
356+
run: cmake -DPCAPPP_BUILD_COVERAGE=ON -DPCAPPP_USE_DPDK=ON -DDPDK_ROOT=${{ github.workspace }}/dpdk/install -S . -B "$BUILD_DIR"
348357

349358
- name: Build PcapPlusPlus
350359
run: cmake --build "$BUILD_DIR" -j
351360

352-
- name: Test Packet++
353-
if: env.avx512 == 'true'
354-
run: ./Packet++Test
355-
working-directory: ${{ github.workspace }}/${{ env.BUILD_DIR }}/Tests/Packet++Test
361+
- name: Setup veth pair
362+
run: |
363+
sudo ip link add veth0 type veth peer name veth1
364+
sudo ip link set veth0 up
365+
sudo ip link set veth1 up
366+
sudo ip addr add 192.168.100.1/24 dev veth0
367+
sudo ip addr add 192.168.100.2/24 dev veth1
356368
357-
- name: Tests skipped (no AVX-512 hardware support)
358-
if: env.avx512 == 'false'
359-
run: echo "Skipping tests since AVX-512 is not supported on the current runner"
369+
- name: Register DPDK library path
370+
run: |
371+
echo "${{ github.workspace }}/dpdk/install/lib/x86_64-linux-gnu" | sudo tee /etc/ld.so.conf.d/dpdk.conf
372+
sudo ldconfig
360373
361-
- name: Check installation
374+
- name: Setup hugepages
362375
run: |
363-
cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR"
364-
cmake --build "$BUILD_DIR" -j
365-
cmake --install "$BUILD_DIR"
376+
sudo mkdir -p /mnt/huge
377+
sudo mount -t hugetlbfs nodev /mnt/huge
378+
echo 512 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
379+
grep HugePages /proc/meminfo
366380
367-
- name: Build Tutorials
381+
- name: Prepare environment for tests
368382
run: |
369-
cmake -DPCAPPP_BUILD_TUTORIALS=ON -S Examples -B build_examples
370-
cmake --build build_examples -j
383+
python3 -m venv .venv
384+
. .venv/bin/activate
385+
python3 -m pip install -r ci/run_tests/requirements.txt
371386
372-
- name: Test Tutorials
373-
run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld
387+
- name: Test PcapPlusPlus
388+
run: |
389+
. .venv/bin/activate
390+
python3 ci/run_tests/run_tests.py --interface eth0 --tcpreplay-interface veth1 --use-sudo --test-suites pcap --pcap-test-args "-t dpdk -d 0 -a --no-pci -a --vdev=net_af_packet0,iface=veth0" --build-dir "$BUILD_DIR"
374391
375-
- name: Save Ccache
376-
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
392+
- name: Create Cobertura Report
393+
run: |
394+
. .venv/bin/activate
395+
python3 -m pip install gcovr==${{ matrix.gcovr-version || '8.6' }}
396+
gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml
397+
398+
- name: Upload Coverage Results
399+
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
377400
with:
378-
path: ${{ env.CCACHE_DIR }}
379-
key: ${{ steps.ccache-restore.outputs.cache-primary-key }}
401+
files: ./coverage.xml
402+
flags: ${{ matrix.dpdk_version }},unittest
403+
fail_ci_if_error: false
404+
verbose: true
405+
env:
406+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
380407

381408
pfring:
382409
runs-on: ubuntu-latest

Pcap++/header/MBufRawPacket.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace pcpp
5656
uint16_t m_MbufDataSize;
5757
bool m_FreeMbuf;
5858

59-
void setMBuf(struct rte_mbuf* mBuf, timespec timestamp);
59+
void setMBuf(struct rte_mbuf* mBuf, timespec timestamp, uint16_t mBufDataSize);
6060
bool init(struct rte_mempool* mempool);
6161
bool initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool);
6262

Pcap++/src/DpdkDevice.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,7 @@ namespace pcpp
802802
MBufRawPacket rawPackets[MAX_BURST_SIZE];
803803
for (uint32_t index = 0; index < numOfPktsReceived; ++index)
804804
{
805-
rawPackets[index].setMBuf(mBufArray[index], time);
805+
rawPackets[index].setMBuf(mBufArray[index], time, pThis->m_MBufDataSize);
806806
}
807807

808808
pThis->m_OnPacketsArriveCallback(rawPackets, numOfPktsReceived, coreId, pThis,
@@ -925,7 +925,7 @@ namespace pcpp
925925
{
926926
struct rte_mbuf* mBuf = mBufArray[index];
927927
MBufRawPacket* newRawPacket = new MBufRawPacket();
928-
newRawPacket->setMBuf(mBuf, time);
928+
newRawPacket->setMBuf(mBuf, time, m_MBufDataSize);
929929
rawPacketsArr.pushBack(newRawPacket);
930930
}
931931

@@ -974,9 +974,12 @@ namespace pcpp
974974
{
975975
struct rte_mbuf* mBuf = mBufArray[index];
976976
if (rawPacketsArr[index] == nullptr)
977+
{
977978
rawPacketsArr[index] = new MBufRawPacket();
979+
rawPacketsArr[index]->init(const_cast<DpdkDevice*>(this));
980+
}
978981

979-
rawPacketsArr[index]->setMBuf(mBuf, time);
982+
rawPacketsArr[index]->setMBuf(mBuf, time, m_MBufDataSize);
980983
}
981984

982985
return packetsReceived;
@@ -1017,7 +1020,7 @@ namespace pcpp
10171020
{
10181021
struct rte_mbuf* mBuf = mBufArray[index];
10191022
MBufRawPacket* newRawPacket = new MBufRawPacket();
1020-
newRawPacket->setMBuf(mBuf, time);
1023+
newRawPacket->setMBuf(mBuf, time, m_MBufDataSize);
10211024
if (packetsArr[index] == nullptr)
10221025
packetsArr[index] = new Packet();
10231026

Pcap++/src/KniDevice.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ namespace pcpp
480480
{
481481
struct rte_mbuf* mBuf = mBufArray[index];
482482
MBufRawPacket* newRawPacket = new MBufRawPacket();
483-
newRawPacket->setMBuf(mBuf, time);
483+
newRawPacket->setMBuf(mBuf, time, RTE_MBUF_DEFAULT_BUF_SIZE);
484484
rawPacketsArr.pushBack(newRawPacket);
485485
}
486486

@@ -524,7 +524,7 @@ namespace pcpp
524524
if (rawPacketsArr[index] == nullptr)
525525
rawPacketsArr[index] = new MBufRawPacket();
526526

527-
rawPacketsArr[index]->setMBuf(mBuf, time);
527+
rawPacketsArr[index]->setMBuf(mBuf, time, RTE_MBUF_DEFAULT_BUF_SIZE);
528528
}
529529

530530
return packetsReceived;
@@ -560,7 +560,7 @@ namespace pcpp
560560
{
561561
struct rte_mbuf* mBuf = mBufArray[index];
562562
MBufRawPacket* newRawPacket = new MBufRawPacket();
563-
newRawPacket->setMBuf(mBuf, time);
563+
newRawPacket->setMBuf(mBuf, time, RTE_MBUF_DEFAULT_BUF_SIZE);
564564
if (packetsArr[index] == nullptr)
565565
packetsArr[index] = new Packet();
566566

@@ -808,7 +808,7 @@ namespace pcpp
808808
MBufRawPacket rawPackets[MAX_BURST_SIZE];
809809
for (uint32_t index = 0; index < numOfPktsReceived; ++index)
810810
{
811-
rawPackets[index].setMBuf(mBufArray[index], time);
811+
rawPackets[index].setMBuf(mBufArray[index], time, RTE_MBUF_DEFAULT_BUF_SIZE);
812812
}
813813

814814
if (!callback(rawPackets, numOfPktsReceived, device, userCookie))
@@ -905,7 +905,7 @@ namespace pcpp
905905

906906
for (uint32_t index = 0; index < numOfPktsReceived; ++index)
907907
{
908-
rawPackets[index].setMBuf(mBufArray[index], time);
908+
rawPackets[index].setMBuf(mBufArray[index], time, RTE_MBUF_DEFAULT_BUF_SIZE);
909909
}
910910

911911
if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie))
@@ -932,7 +932,7 @@ namespace pcpp
932932

933933
for (uint32_t index = 0; index < numOfPktsReceived; ++index)
934934
{
935-
rawPackets[index].setMBuf(mBufArray[index], time);
935+
rawPackets[index].setMBuf(mBufArray[index], time, RTE_MBUF_DEFAULT_BUF_SIZE);
936936
}
937937

938938
if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie))

Pcap++/src/MBufRawPacket.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ namespace pcpp
131131
return;
132132
}
133133

134-
setMBuf(newMbuf, other.m_TimeStamp);
134+
setMBuf(newMbuf, other.m_TimeStamp, m_MbufDataSize);
135135

136136
m_RawPacketSet = false;
137137

@@ -328,17 +328,19 @@ namespace pcpp
328328
return true;
329329
}
330330

331-
void MBufRawPacket::setMBuf(struct rte_mbuf* mBuf, timespec timestamp)
331+
void MBufRawPacket::setMBuf(struct rte_mbuf* mBuf, timespec timestamp, uint16_t mBufDataSize)
332332
{
333333
if (mBuf == nullptr)
334334
{
335335
PCPP_LOG_ERROR("mbuf to set is nullptr");
336336
return;
337337
}
338338

339-
RawPacket::setRawData(rte_pktmbuf_mtod(mBuf, const uint8_t*), rte_pktmbuf_pkt_len(mBuf), timestamp,
340-
LINKTYPE_ETHERNET);
341339
m_MBuf = mBuf;
340+
m_MbufDataSize = mBufDataSize;
341+
auto mBufDataLen = rte_pktmbuf_pkt_len(mBuf);
342+
m_RawDataLen = mBufDataLen;
343+
RawPacket::setRawData(rte_pktmbuf_mtod(mBuf, const uint8_t*), mBufDataLen, timestamp, LINKTYPE_ETHERNET);
342344
}
343345

344346
} // namespace pcpp

Tests/Pcap++Test/Common/GlobalTestArgs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <string>
4+
#include <vector>
45
#include <cstdint>
56

67
struct PcapTestArgs
@@ -10,5 +11,6 @@ struct PcapTestArgs
1011
std::string remoteIp;
1112
uint16_t remotePort;
1213
int dpdkPort;
14+
std::vector<std::string> dpdkArgs;
1315
std::string kniIp;
1416
};

Tests/Pcap++Test/Common/TestUtils.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,15 @@ void testSetUp()
103103
{
104104
coreMask |= pcpp::SystemCores::IdToSystemCore[i].Mask;
105105
}
106-
pcpp::DpdkDeviceList::initDpdk(coreMask, 16383);
106+
107+
std::vector<char*> dpdkArgv;
108+
dpdkArgv.reserve(PcapTestGlobalArgs.dpdkArgs.size());
109+
std::transform(PcapTestGlobalArgs.dpdkArgs.begin(), PcapTestGlobalArgs.dpdkArgs.end(),
110+
std::back_inserter(dpdkArgv), [](auto& arg) { return const_cast<char*>(arg.c_str()); });
111+
int dpdkArgc = dpdkArgv.empty() ? 0 : static_cast<int>(dpdkArgv.size());
112+
char** dpdkArgvPtr = dpdkArgv.empty() ? nullptr : dpdkArgv.data();
113+
114+
pcpp::DpdkDeviceList::initDpdk(coreMask, 16383, 0, 0, dpdkArgc, dpdkArgvPtr, "pcapplusplusapp", false);
107115
}
108116
#endif
109117
}

Tests/Pcap++Test/Tests/DpdkTests.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,6 @@ class DpdkTestWorkerThread : public pcpp::DpdkWorkerThread
219219
uint16_t packetReceived = m_DpdkDevice->receivePackets(mBufArr, 32, m_QueueId);
220220
lock.unlock();
221221
m_PacketCount += packetReceived;
222-
lock.lock();
223-
uint16_t packetsSent = m_DpdkDevice->sendPackets(mBufArr, packetReceived, m_QueueId);
224-
if (packetsSent != packetReceived)
225-
{
226-
return false;
227-
}
228222
}
229223

230224
for (int i = 0; i < 32; i++)

Tests/Pcap++Test/main.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ static struct option PcapTestOptions[] = {
1313
{ "remote-ip", required_argument, nullptr, 'r' },
1414
{ "remote-port", required_argument, nullptr, 'p' },
1515
{ "dpdk-port", required_argument, nullptr, 'd' },
16+
{ "dpdk-args", required_argument, nullptr, 'a' },
1617
{ "no-networking", no_argument, nullptr, 'n' },
1718
{ "verbose", no_argument, nullptr, 'v' },
1819
{ "mem-verbose", no_argument, nullptr, 'm' },
@@ -36,6 +37,7 @@ void printUsage()
3637
<< "-r --remote-ip IP of remote machine running rpcapd to test remote capture\n"
3738
<< "-p --remote-port Port of remote machine running rpcapd to test remote capture\n"
3839
<< "-d --dpdk-port The DPDK NIC port to test. Required if compiling with DPDK\n"
40+
<< "-a --dpdk-args DPDK args to pass to tests\n"
3941
<< "-n --no-networking Do not run tests that requires networking\n"
4042
<< "-v --verbose Run in verbose mode (emits more output in several tests)\n"
4143
<< "-m --mem-verbose Output information about each memory allocation and deallocation\n"
@@ -66,7 +68,7 @@ int main(int argc, char* argv[])
6668

6769
int optionIndex = 0;
6870
int opt = 0;
69-
while ((opt = getopt_long(argc, argv, "k:i:br:p:d:nvt:x:smw", PcapTestOptions, &optionIndex)) != -1)
71+
while ((opt = getopt_long(argc, argv, "k:i:br:p:d:a:nvt:x:smw", PcapTestOptions, &optionIndex)) != -1)
7072
{
7173
switch (opt)
7274
{
@@ -90,6 +92,9 @@ int main(int argc, char* argv[])
9092
case 'd':
9193
PcapTestGlobalArgs.dpdkPort = (int)atoi(optarg);
9294
break;
95+
case 'a':
96+
PcapTestGlobalArgs.dpdkArgs.push_back(optarg);
97+
break;
9398
case 'n':
9499
runWithNetworking = false;
95100
break;

0 commit comments

Comments
 (0)