#include "xsk.hh"
#ifdef DEBUG_UMEM
-namespace {
+namespace
+{
struct UmemEntryStatus
{
- enum class Status: uint8_t { Free, FillQueue, Received, TXQueue };
+ enum class Status : uint8_t
+ {
+ Free,
+ FillQueue,
+ Received,
+ TXQueue
+ };
Status status{Status::Free};
};
uniqueEmptyFrameOffset.reserve(frameNum);
{
for (uint64_t i = 0; i < frameNum; i++) {
- //uniqueEmptyFrameOffset.push_back(i * frameSize);
uniqueEmptyFrameOffset.push_back(i * frameSize + XDP_PACKET_HEADROOM);
#ifdef DEBUG_UMEM
{
void XskSocket::fillFq(uint32_t fillSize) noexcept
{
{
-#warning why are we collecting frames from unique into shared here, even though we need unique ones?
+ // if we have less than holdThreshold frames in the shared queue (which might be an issue
+ // when the XskWorker needs empty frames), move frames from the unique container into the
+ // shared one. This might not be optimal right now.
auto frames = sharedEmptyFrameOffset->lock();
if (frames->size() < holdThreshold) {
const auto moveSize = std::min(holdThreshold - frames->size(), uniqueEmptyFrameOffset.size());
if (moveSize > 0) {
+ // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
frames->insert(frames->end(), std::make_move_iterator(uniqueEmptyFrameOffset.end() - moveSize), std::make_move_iterator(uniqueEmptyFrameOffset.end()));
uniqueEmptyFrameOffset.resize(uniqueEmptyFrameOffset.size() - moveSize);
}
return packet.getFrameOffsetFrom(umem.bufBase);
}
-[[nodiscard]] int XskSocket::xskFd() const noexcept {
+[[nodiscard]] int XskSocket::xskFd() const noexcept
+{
return xsk_socket__fd(socket.get());
}
for (; processed < recvSize; processed++) {
try {
const auto* desc = xsk_ring_cons__rx_desc(&rx, idx++);
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr)
XskPacket packet = XskPacket(reinterpret_cast<uint8_t*>(desc->addr + baseAddr), desc->len, frameSize);
#ifdef DEBUG_UMEM
checkUmemIntegrity(__PRETTY_FUNCTION__, __LINE__, frameOffset(packet), {UmemEntryStatus::Status::Free, UmemEntryStatus::Status::FillQueue}, UmemEntryStatus::Status::Received);
void XskPacket::setUDPHeader(const udphdr& udpHeader) noexcept
{
assert(frameLength >= (sizeof(ethhdr) + (v6 ? sizeof(ipv6hdr) : sizeof(iphdr)) + sizeof(udpHeader)));
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
memcpy(frame + getL4HeaderOffset(), &udpHeader, sizeof(udpHeader));
}
{
auto ethHeader = getEthernetHeader();
{
- std::array<uint8_t, ETH_ALEN> tmp;
+ std::array<uint8_t, ETH_ALEN> tmp{};
static_assert(tmp.size() == sizeof(ethHeader.h_dest), "Size Error");
static_assert(tmp.size() == sizeof(ethHeader.h_source), "Size Error");
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(tmp.data(), ethHeader.h_dest, tmp.size());
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(ethHeader.h_dest, ethHeader.h_source, tmp.size());
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(ethHeader.h_source, tmp.data(), tmp.size());
}
if (ethHeader.h_proto == htons(ETH_P_IPV6)) {
void XskPacket::setAddr(const ComboAddress& from_, MACAddr fromMAC, const ComboAddress& to_, MACAddr toMAC) noexcept
{
auto ethHeader = getEthernetHeader();
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(ethHeader.h_dest, toMAC.data(), toMAC.size());
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(ethHeader.h_source, fromMAC.data(), fromMAC.size());
setEthernetHeader(ethHeader);
to = to_;
uint32_t words[3];
};
};
- struct ipv4_pseudo_header_t pseudo_header;
+ struct ipv4_pseudo_header_t pseudo_header{};
static_assert(sizeof(pseudo_header) == 12, "IPv4 pseudo-header size is incorrect");
/* Fill in the pseudo-header. */
uint32_t words[10];
};
};
- struct ipv6_pseudo_header_t pseudo_header;
+ struct ipv6_pseudo_header_t pseudo_header{};
static_assert(sizeof(pseudo_header) == 40, "IPv6 pseudo-header size is incorrect");
/* Fill in the pseudo-header. */
void XskWorker::waitForXskSocket() const noexcept
{
- uint64_t x = read(workerWaker, &x, sizeof(x));
+ uint64_t value = read(workerWaker, &value, sizeof(value));
}
void XskWorker::notifyXskSocket() const
return packet.getFrameOffsetFrom(umemBufBase);
}
-void XskWorker::notifyWorker() noexcept
+void XskWorker::notifyWorker() const
{
notify(workerWaker);
}
throw std::runtime_error("Unable to get MAC address for interface " + ifName + ": name too long");
}
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
strncpy(ifr.ifr_name, ifName.c_str(), ifName.length() + 1);
if (ioctl(desc.getHandle(), SIOCGIFHWADDR, &ifr) < 0 || ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
throw std::runtime_error("Error getting MAC address for interface " + ifName);
}
static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= std::tuple_size<decltype(source)>{}, "The size of an ARPHRD_ETHER MAC address is smaller than expected");
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
memcpy(source.data(), ifr.ifr_hwaddr.sa_data, source.size());
}
auto frames = sharedEmptyFrameOffset->lock();
const auto moveSize = std::min(static_cast<size_t>(32), frames->size());
if (moveSize > 0) {
+ // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
uniqueEmptyFrameOffset.insert(uniqueEmptyFrameOffset.end(), std::make_move_iterator(frames->end() - moveSize), std::make_move_iterator(frames->end()));
frames->resize(frames->size() - moveSize);
}
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
+#include <cstdint>
#include <memory>
#include <poll.h>
#include <queue>
#include <stdexcept>
#include <string>
-//#include <sys/types.h>
#include <unistd.h>
#include <unordered_map>
#include <vector>
static constexpr uint32_t txCapacity = XSK_RING_PROD__DEFAULT_NUM_DESCS * 2;
constexpr static bool isPowOfTwo(uint32_t value) noexcept;
- [[nodiscard]] static int timeDifference(const timespec& t1, const timespec& t2) noexcept;
+ [[nodiscard]] static int timeDifference(const timespec& lhs, const timespec& rhs) noexcept;
[[nodiscard]] uint64_t frameOffset(const XskPacket& packet) const noexcept;
[[nodiscard]] int firstTimeout();
[[nodiscard]] __be16 tcp_udp_v4_checksum(const struct iphdr*) const noexcept;
// You must set l4Header.check = 0 before calling this method
[[nodiscard]] __be16 tcp_udp_v6_checksum(const struct ipv6hdr*) const noexcept;
- /* offset of the L4 (udphdr) header (after ethhdr and iphdr/ipv6hdr) */
+ /* offset of the L4 (udphdr) header (after ethhdr and iphdr/ipv6hdr) */
[[nodiscard]] size_t getL4HeaderOffset() const noexcept;
/* offset of the data after the UDP header */
[[nodiscard]] size_t getDataOffset() const noexcept;
return frame - base;
}
};
-bool operator<(const XskPacket& s1, const XskPacket& s2) noexcept;
+bool operator<(const XskPacket& lhs, const XskPacket& rhs) noexcept;
/* g++ defines __SANITIZE_THREAD__
clang++ supports the nice __has_feature(thread_sanitizer),
class XskWorker
{
#if defined(__SANITIZE_THREAD__)
- using XskPacketRing = LockGuarded<boost::lockfree::spsc_queue<XskPacket, boost::lockfree::capacity<XSK_RING_CONS__DEFAULT_NUM_DESCS*2>>>;
+ using XskPacketRing = LockGuarded<boost::lockfree::spsc_queue<XskPacket, boost::lockfree::capacity<XSK_RING_CONS__DEFAULT_NUM_DESCS * 2>>>;
#else
- using XskPacketRing = boost::lockfree::spsc_queue<XskPacket, boost::lockfree::capacity<XSK_RING_CONS__DEFAULT_NUM_DESCS*2>>;
+ using XskPacketRing = boost::lockfree::spsc_queue<XskPacket, boost::lockfree::capacity<XSK_RING_CONS__DEFAULT_NUM_DESCS * 2>>;
#endif
public:
// queue of packets processed by this worker (to be sent, or discarded)
XskPacketRing outgoingPacketsQueue;
- uint8_t* umemBufBase;
+ uint8_t* umemBufBase{nullptr};
// list of frames that are shared with the XskRouter
std::shared_ptr<LockGuarded<vector<uint64_t>>> sharedEmptyFrameOffset;
// list of frames that we own, used to generate new packets (health-check)
XskWorker();
static int createEventfd();
- static void notify(int fd);
+ static void notify(int desc);
static std::shared_ptr<XskWorker> create();
void pushToProcessingQueue(XskPacket& packet);
void pushToSendQueue(XskPacket& packet);
void markAsFree(const XskPacket& packet);
// notify worker that at least one packet is available for processing
- void notifyWorker() noexcept;
+ void notifyWorker() const;
// notify the router that packets are ready to be sent
void notifyXskSocket() const;
void waitForXskSocket() const noexcept;