1414
1515#include " parser.hpp"
1616
17+ #include < algorithm>
1718#include < cstdio>
1819#include < cstring>
1920#include < iostream>
21+ #include < memory>
22+ #include < span>
2023
2124#include < ipfixprobe/pluginFactory/pluginManifest.hpp>
2225#include < ipfixprobe/pluginFactory/pluginRegistrar.hpp>
@@ -43,7 +46,33 @@ static const PluginManifest ndpPluginManifest = {
4346 },
4447};
4548
49+ static std::vector<std::string> parseDevices (const std::string& input)
50+ {
51+ std::vector<std::string> result;
52+
53+ size_t colon_pos = input.find_last_of (' :' );
54+ std::string suffix;
55+ std::string devices;
56+
57+ if (colon_pos != std::string::npos) {
58+ devices = input.substr (0 , colon_pos);
59+ suffix = input.substr (colon_pos);
60+ } else {
61+ devices = input;
62+ suffix = " " ;
63+ }
64+
65+ std::stringstream ss (devices);
66+ std::string dev;
67+ while (std::getline (ss, dev, ' ,' )) {
68+ result.push_back (dev + suffix);
69+ }
70+
71+ return result;
72+ }
73+
4674NdpPacketReader::NdpPacketReader (const std::string& params)
75+ : ndp_packet_burst(new ndp_packet[64 ])
4776{
4877 init (params.c_str ());
4978}
@@ -65,18 +94,29 @@ void NdpPacketReader::init(const char* params)
6594 if (parser.m_dev .empty ()) {
6695 throw PluginError (" specify device path" );
6796 }
97+
6898 init_ifc (parser.m_dev );
6999}
70100
71101void NdpPacketReader::close ()
72102{
73- ndpReader.close ();
103+ for (size_t i = 0 ; i < m_readers_count; i++) {
104+ ndpReader[i].close ();
105+ }
74106}
75107
76108void NdpPacketReader::init_ifc (const std::string& dev)
77109{
78- if (ndpReader.init_interface (dev) != 0 ) {
79- throw PluginError (ndpReader.error_msg );
110+ const std::vector<std::string> devs = parseDevices (dev);
111+ m_readers_count = devs.size ();
112+ if (m_readers_count > 2 ) {
113+ throw PluginError (" too many devices specified" );
114+ }
115+
116+ for (size_t i = 0 ; i < m_readers_count; i++) {
117+ if (ndpReader[i].init_interface (devs[i]) != 0 ) {
118+ throw PluginError (ndpReader[i].error_msg );
119+ }
80120 }
81121}
82122
@@ -85,38 +125,63 @@ InputPlugin::Result NdpPacketReader::get(PacketBlock& packets)
85125 parser_opt_t opt = {&packets, false , false , 0 };
86126 struct ndp_packet * ndp_packet;
87127 struct timeval timestamp;
88- size_t read_pkts = 0 ;
89128 int ret = -1 ;
90129
91130 packets.cnt = 0 ;
92- for (unsigned i = 0 ; i < packets.size ; i++) {
93- ret = ndpReader.get_pkt (&ndp_packet, ×tamp);
94- if (ret == 0 ) {
95- if (opt.pblock ->cnt ) {
96- break ;
97- }
98- return Result::TIMEOUT;
99- } else if (ret < 0 ) {
100- // Error occured.
101- throw PluginError (ndpReader.error_msg );
131+ constexpr size_t maxBurstSize = 64 ;
132+ size_t burstSize = std::min (packets.size , maxBurstSize);
133+ std::span<struct ndp_packet > packetSpan (ndp_packet_burst.get (), burstSize);
134+ std::span<timeval> timestampSpan (timestamps);
135+
136+ size_t reader_index = (m_reader_idx++) & (m_readers_count - 1 );
137+ NdpReader& reader = ndpReader[reader_index];
138+ int received = reader.get_packets (packetSpan, timestampSpan);
139+
140+ if (received < 32 ) {
141+ std::span<struct ndp_packet > packetSpan (
142+ ndp_packet_burst.get () + received,
143+ burstSize - received);
144+ std::span<timeval> timestampSpan (timestamps.data () + received, burstSize - received);
145+
146+ size_t reader_index = (m_reader_idx++) & (m_readers_count - 1 );
147+ NdpReader& reader = ndpReader[reader_index];
148+ received += reader.get_packets (packetSpan, timestampSpan);
149+ }
150+
151+ for (unsigned i = 0 ; i < received; ++i) {
152+ ndp_packet = &ndp_packet_burst[i];
153+ timestamp = timestamps[i];
154+
155+ if (ndp_packet->data_length == 0 ) {
156+ continue ; // Skip empty packets
102157 }
103- read_pkts++;
158+
104159 parse_packet (
105160 &opt,
106161 m_parser_stats,
107162 timestamp,
108163 ndp_packet->data ,
109164 ndp_packet->data_length ,
110165 ndp_packet->data_length );
166+
167+ if (opt.pblock ->cnt >= packets.size ) {
168+ break ;
169+ }
111170 }
112171
113- m_seen += read_pkts ;
172+ m_seen += received ;
114173 m_parsed += opt.pblock ->cnt ;
115174
116- m_stats.receivedPackets += read_pkts ;
175+ m_stats.receivedPackets += received ;
117176 m_stats.receivedBytes += packets.bytes ;
118177
119- return opt.pblock ->cnt ? Result::PARSED : Result::NOT_PARSED;
178+ if (opt.pblock ->cnt ) {
179+ return Result::PARSED;
180+ } else if (received == 0 ) {
181+ return Result::TIMEOUT;
182+ } else {
183+ return Result::NOT_PARSED;
184+ }
120185}
121186
122187void NdpPacketReader::configure_telemetry_dirs (
0 commit comments