27#include "fastmm/core/config_macros.hpp"
30#include "fastmm/net/udp_frame.hpp"
41struct DpdkSubscription {
95 void close() noexcept;
96 [[nodiscard]] const std::
string& error() const noexcept {
return error_; }
97 [[nodiscard]]
const std::string& port_name() const noexcept {
return port_name_; }
99 [[nodiscard]]
const std::string& exception_interface() const noexcept {
return exc_ifname_; }
102 std::size_t poll(H&& handler)
noexcept {
103 const std::uint32_t n = rx_burst();
105 if (FASTMM_UNLIKELY(exc_ != kNoPort)) service_exception();
111 std::size_t delivered = 0;
112 for (std::uint32_t i = 0; i < n; ++i) {
113 const UdpFrame f = parse_udp_frame(frames_[i], verify_checksums_);
114 if (FASTMM_UNLIKELY(f.status != FrameStatus::Ok)) {
115 const bool other = f.status == FrameStatus::NotIpv4 || f.status == FrameStatus::NotUdp ||
116 f.status == FrameStatus::Fragment;
117 ++(other ? stats_.other : stats_.bad_frames);
118 if (other) divert(i);
121 const Route* route =
nullptr;
122 for (
const Route& r : routes_) {
123 if (r.dst_ip == f.dst_ip && r.dst_port == f.dst_port) {
128 if (route ==
nullptr) {
133 meta.src_ip = f.src_ip;
134 meta.dst_ip = f.dst_ip;
135 meta.dst_port = f.dst_port;
136 meta.line = route->line;
137 handler(f.payload,
static_cast<const RxMeta&
>(meta));
139 stats_.bytes += f.payload.size();
142 stats_.datagrams += delivered;
143 if (FASTMM_UNLIKELY(exc_ != kNoPort)) service_exception();
148 int refresh_stats() noexcept;
149 [[nodiscard]] const DpdkStats& stats() const noexcept {
return stats_; }
152 static constexpr std::uint16_t kNoPort = 0xFFFF;
155 std::uint32_t dst_ip;
156 std::uint16_t dst_port;
159 std::uint32_t rx_burst() noexcept;
160 void free_burst(std::uint32_t n) noexcept;
162 void divert(std::uint32_t i) noexcept;
164 void service_exception() noexcept;
165 bool send_frame(std::span<const std::
byte> frame) noexcept;
166 int open_exception(const
DpdkConfig& cfg,
unsigned sock);
167 int fail(
int err, std::
string msg);
169 std::vector<std::span<const std::
byte>> frames_;
170 std::vector<
void*> mbufs_;
171 std::vector<
void*> to_exc_;
172 std::vector<
void*> exc_rx_;
173 std::vector<Route> routes_;
174 std::vector<std::uint32_t> unicast_;
175 std::vector<
int> join_fds_;
176 void* pool_ =
nullptr;
178 std::
string port_name_;
179 std::
string exc_ifname_;
181 std::array<std::uint8_t, 6> mac_{};
182 std::uint32_t to_exc_n_ = 0;
183 std::uint64_t exc_interval_cycles_ = 0;
184 std::uint64_t exc_next_ = 0;
185 std::uint16_t port_ = 0;
186 std::uint16_t exc_ = kNoPort;
187 std::uint16_t batch_ = 32;
188 bool started_ =
false;
189 bool exc_started_ =
false;
190 bool verify_checksums_ =
false;
193static_assert(DatagramSource<DpdkDatagramSource>);
Definition dpdk_datagram_source.hpp:86
DpdkDatagramSource()=default
DpdkDatagramSource & operator=(const DpdkDatagramSource &)=delete
DpdkDatagramSource(const DpdkDatagramSource &)=delete
Datagram receive interface for multicast market data (ADR-0015, section 1).
Definition reactor.hpp:37
bool dpdk_available() noexcept
True when this build has the DPDK backend.
Timestamp wall_now() noexcept
CLOCK_REALTIME via vDSO (~20 ns). Implemented in src/core/time.cpp.
FASTMM_FORCE_INLINE Cycles rdtscp() noexcept
Serialising read (rdtscp) is what latency hops want: it waits for prior loads to retire.
Definition time.hpp:66
constexpr Unexpected< std::decay_t< E > > fail(E &&e) noexcept
Definition result.hpp:25
std::int64_t ns
Definition time.hpp:46
Definition dpdk_datagram_source.hpp:50
std::string exception_ip
Definition dpdk_datagram_source.hpp:62
std::uint32_t batch
frames per rx burst, at most 256
Definition dpdk_datagram_source.hpp:57
std::string port
ethdev name ("net_af_packet0", "0000:00:06.0"); "" = first
Definition dpdk_datagram_source.hpp:52
std::vector< DpdkSubscription > subscriptions
line = index, at most 256
Definition dpdk_datagram_source.hpp:53
bool verify_udp_checksum
Definition dpdk_datagram_source.hpp:58
std::uint32_t mbufs
Definition dpdk_datagram_source.hpp:56
std::vector< std::string > eal_args
argv[1..] of rte_eal_init
Definition dpdk_datagram_source.hpp:51
std::int64_t exception_interval_ns
Definition dpdk_datagram_source.hpp:63
std::uint16_t tx_descriptors
Definition dpdk_datagram_source.hpp:55
std::uint16_t rx_descriptors
Definition dpdk_datagram_source.hpp:54
std::string exception_port
Kernel exception path: ethdev name of a net_tap vdev ("" = none).
Definition dpdk_datagram_source.hpp:61
Definition dpdk_datagram_source.hpp:66
std::uint64_t to_kernel
frames passed to the exception port
Definition dpdk_datagram_source.hpp:72
std::uint64_t bad_frames
truncated, bad IPv4 header, lengths or checksums, chained mbufs
Definition dpdk_datagram_source.hpp:69
std::uint64_t datagrams
Definition dpdk_datagram_source.hpp:67
std::uint64_t other
not IPv4 UDP (ARP, TCP, IGMP, fragments): not for this source
Definition dpdk_datagram_source.hpp:70
std::uint64_t from_kernel
frames the kernel sent through the exception port
Definition dpdk_datagram_source.hpp:73
std::uint64_t arp_replies
answered here (no exception port)
Definition dpdk_datagram_source.hpp:74
std::uint64_t ipackets
rte_eth_stats_get, as of the last refresh_stats()
Definition dpdk_datagram_source.hpp:77
std::uint64_t ierrors
Definition dpdk_datagram_source.hpp:79
std::uint64_t rx_nombuf
Definition dpdk_datagram_source.hpp:80
std::uint64_t imissed
Definition dpdk_datagram_source.hpp:78
std::uint64_t tx_drops
ARP replies not sent: no mbuf, or the TX queue was full.
Definition dpdk_datagram_source.hpp:75
std::uint64_t unmatched
UDP, but no subscription.
Definition dpdk_datagram_source.hpp:71
std::uint64_t bytes
Definition dpdk_datagram_source.hpp:68
std::uint32_t group
IPv4 multicast group or local unicast address, network byte order.
Definition dpdk_datagram_source.hpp:45
std::uint32_t source
network byte order; 0 = any (joins only)
Definition dpdk_datagram_source.hpp:47
std::uint16_t port
host byte order
Definition dpdk_datagram_source.hpp:46
std::string interface
kernel netdev for the IGMP join; "" = no join
Definition dpdk_datagram_source.hpp:44