diff --git a/tests/nexus/platform/nexus_pcap.cpp b/tests/nexus/platform/nexus_pcap.cpp index 230f91a09..62181455f 100644 --- a/tests/nexus/platform/nexus_pcap.cpp +++ b/tests/nexus/platform/nexus_pcap.cpp @@ -34,6 +34,18 @@ namespace ot { namespace Nexus { +OT_TOOL_PACKED_BEGIN +struct Epb +{ + uint32_t mBlockType; + uint32_t mBlockTotalLength; + uint32_t mInterfaceId; + uint32_t mTimestampHigh; + uint32_t mTimestampLow; + uint32_t mCapturedLen; + uint32_t mOriginalLen; +} OT_TOOL_PACKED_END; + Pcap::Pcap(void) : mFile(nullptr) { @@ -89,6 +101,14 @@ void Pcap::Open(const char *aFilename) idb.mBlockTotalLength2 = idb.mBlockTotalLength; VerifyOrExit(fwrite(&idb, sizeof(idb), 1, mFile) == 1, Close()); + ClearAllBytes(idb); + idb.mBlockType = LittleEndian::HostSwap(kPcapngIdbType); + idb.mBlockTotalLength = LittleEndian::HostSwap(static_cast(sizeof(idb))); + idb.mLinkType = LittleEndian::HostSwap(static_cast(kPcapngLinkTypeIPv6)); + idb.mSnapLen = LittleEndian::HostSwap(kPcapngSnapLen); + idb.mBlockTotalLength2 = idb.mBlockTotalLength; + VerifyOrExit(fwrite(&idb, sizeof(idb), 1, mFile) == 1, Close()); + VerifyOrExit(fflush(mFile) == 0, Close()); exit: @@ -108,17 +128,7 @@ exit: void Pcap::WriteFrame(const otRadioFrame &aFrame, uint64_t aTimeUs) { - OT_TOOL_PACKED_BEGIN - struct Epb - { - uint32_t mBlockType; - uint32_t mBlockTotalLength; - uint32_t mInterfaceId; - uint32_t mTimestampHigh; - uint32_t mTimestampLow; - uint32_t mCapturedLen; - uint32_t mOriginalLen; - } OT_TOOL_PACKED_END epb; + Epb epb; OT_TOOL_PACKED_BEGIN struct TapHeader @@ -147,7 +157,7 @@ void Pcap::WriteFrame(const otRadioFrame &aFrame, uint64_t aTimeUs) ClearAllBytes(epb); epb.mBlockType = LittleEndian::HostSwap(kPcapngEpbType); epb.mBlockTotalLength = LittleEndian::HostSwap(blockTotalLength); - epb.mInterfaceId = 0; + epb.mInterfaceId = LittleEndian::HostSwap(0u); epb.mTimestampHigh = LittleEndian::HostSwap(static_cast(aTimeUs >> 32)); epb.mTimestampLow = LittleEndian::HostSwap(static_cast(aTimeUs & 0xffffffff)); epb.mCapturedLen = LittleEndian::HostSwap(packetLen); @@ -191,5 +201,43 @@ exit: return; } +void Pcap::WritePacket(const uint8_t *aBuffer, uint16_t aLength, uint64_t aTimeUs) +{ + Epb epb; + + uint32_t paddedLen; + uint32_t blockTotalLength; + uint32_t padding = 0; + + VerifyOrExit(mFile != nullptr); + + paddedLen = (aLength + 3) & ~3u; + blockTotalLength = sizeof(epb) + paddedLen + sizeof(uint32_t); + + ClearAllBytes(epb); + epb.mBlockType = LittleEndian::HostSwap(kPcapngEpbType); + epb.mBlockTotalLength = LittleEndian::HostSwap(blockTotalLength); + epb.mInterfaceId = LittleEndian::HostSwap(1u); // Use Interface ID 1 for IPv6 + epb.mTimestampHigh = LittleEndian::HostSwap(static_cast(aTimeUs >> 32)); + epb.mTimestampLow = LittleEndian::HostSwap(static_cast(aTimeUs & 0xffffffff)); + epb.mCapturedLen = LittleEndian::HostSwap(static_cast(aLength)); + epb.mOriginalLen = LittleEndian::HostSwap(static_cast(aLength)); + VerifyOrExit(fwrite(&epb, sizeof(epb), 1, mFile) == 1, Close()); + + VerifyOrExit(fwrite(aBuffer, aLength, 1, mFile) == 1, Close()); + + if (paddedLen > aLength) + { + VerifyOrExit(fwrite(&padding, paddedLen - aLength, 1, mFile) == 1, Close()); + } + + VerifyOrExit(fwrite(&epb.mBlockTotalLength, sizeof(epb.mBlockTotalLength), 1, mFile) == 1, Close()); + + VerifyOrExit(fflush(mFile) == 0, Close()); + +exit: + return; +} + } // namespace Nexus } // namespace ot diff --git a/tests/nexus/platform/nexus_pcap.hpp b/tests/nexus/platform/nexus_pcap.hpp index 201ba7b72..b26f700f8 100644 --- a/tests/nexus/platform/nexus_pcap.hpp +++ b/tests/nexus/platform/nexus_pcap.hpp @@ -63,6 +63,15 @@ public: */ void WriteFrame(const otRadioFrame &aFrame, uint64_t aTimeUs); + /** + * Writes a packet to the pcapng file. + * + * @param[in] aBuffer The packet buffer to write. + * @param[in] aLength The packet length. + * @param[in] aTimeUs The timestamp in microseconds. + */ + void WritePacket(const uint8_t *aBuffer, uint16_t aLength, uint64_t aTimeUs); + private: static constexpr uint32_t kPcapngShbType = 0x0a0d0d0a; static constexpr uint32_t kPcapngByteOrderMagic = 0x1a2b3c4d; @@ -72,6 +81,7 @@ private: static constexpr uint32_t kPcapngEpbType = 0x00000006; static constexpr uint32_t kPcapngSnapLen = 65535; static constexpr uint32_t kPcapngLinkTypeIeee802154 = 283; // DLT_IEEE802_15_4_TAP + static constexpr uint32_t kPcapngLinkTypeIPv6 = 101; // LINKTYPE_RAW static constexpr uint8_t kTapVersion = 0;