Skip to content

Commit 5a261e4

Browse files
authored
Changed m_PfRingDescriptors to only contain active channels. (#1765)
* Changed `m_PfRingDescriptors` to only contain active channels. - `m_PfRingDescriptors` is no longer initialized to MAX_NUM_RX_CHANNELS. Instead the buffer is only reserved. - New channels are added to `m_PfRingDescriptors` only after passing initialization. - Added helper function `closeAllRxChannels` that closes and clears `m_PfRingDescriptors`. - Removed variable `m_NumOfOpenedRxChannels`. `m_PfRingDescriptors::size()` should be used to fetch the number of active channels instead. - Replaced `for` loops with `foreach` loops where possible. * Fixed signed to unsigned comparison warnings. * Added checks to skip flushing the ringChannel on send packet if the device is closed. * Lint
1 parent 04b7337 commit 5a261e4

File tree

2 files changed

+81
-61
lines changed

2 files changed

+81
-61
lines changed

Pcap++/header/PfRingDevice.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ namespace pcpp
6060
};
6161

6262
std::vector<pfring*> m_PfRingDescriptors;
63-
uint8_t m_NumOfOpenedRxChannels;
6463
std::string m_DeviceName;
6564
int m_InterfaceIndex;
6665
MacAddress m_MacAddress;
@@ -79,6 +78,8 @@ namespace pcpp
7978
void captureThreadMain(std::shared_ptr<StartupBlock> startupBlock);
8079

8180
int openSingleRxChannel(const char* deviceName, pfring*& ring);
81+
/// Closes all opened RX channels and clears the opened channels list (m_PfRingDescriptors)
82+
void closeAllRxChannels();
8283

8384
bool getIsHwClockEnable()
8485
{
@@ -88,7 +89,7 @@ namespace pcpp
8889
bool setPfRingDeviceClock(pfring* ring);
8990

9091
void clearCoreConfiguration();
91-
int getCoresInUseCount() const;
92+
size_t getCoresInUseCount() const;
9293

9394
void setPfRingDeviceAttributes();
9495

@@ -211,7 +212,7 @@ namespace pcpp
211212
/// @return Number of opened RX channels
212213
uint8_t getNumOfOpenedRxChannels() const
213214
{
214-
return m_NumOfOpenedRxChannels;
215+
return static_cast<uint8_t>(m_PfRingDescriptors.size());
215216
}
216217

217218
/// Gets the total number of RX channels (RX queues) this interface has

Pcap++/src/PfRingDevice.cpp

Lines changed: 77 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ namespace pcpp
4040

4141
PfRingDevice::PfRingDevice(const char* deviceName) : m_MacAddress(MacAddress::Zero)
4242
{
43-
m_NumOfOpenedRxChannels = 0;
4443
m_DeviceOpened = false;
4544
m_DeviceName = std::string(deviceName);
4645
m_InterfaceIndex = -1;
@@ -52,7 +51,7 @@ namespace pcpp
5251
m_DeviceMTU = 0;
5352
m_IsFilterCurrentlySet = false;
5453

55-
m_PfRingDescriptors.resize(MAX_NUM_RX_CHANNELS);
54+
m_PfRingDescriptors.reserve(MAX_NUM_RX_CHANNELS);
5655
}
5756

5857
PfRingDevice::~PfRingDevice()
@@ -68,15 +67,15 @@ namespace pcpp
6867
return false;
6968
}
7069

71-
m_NumOfOpenedRxChannels = 0;
72-
7370
PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "]");
74-
int res = openSingleRxChannel(m_DeviceName.c_str(), m_PfRingDescriptors[0]);
71+
pfring* newChannel;
72+
int res = openSingleRxChannel(m_DeviceName.c_str(), newChannel);
7573
if (res == 0)
7674
{
77-
PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "]");
78-
m_NumOfOpenedRxChannels = 1;
75+
// Adds the newly opened channel to the list of opened channels
76+
m_PfRingDescriptors.push_back(newChannel);
7977
m_DeviceOpened = true;
78+
PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "]");
8079
return true;
8180
}
8281
else if (res == 1)
@@ -127,6 +126,18 @@ namespace pcpp
127126
return 0;
128127
}
129128

129+
void PfRingDevice::closeAllRxChannels()
130+
{
131+
for (pfring* rxChannel : m_PfRingDescriptors)
132+
{
133+
if (rxChannel != nullptr)
134+
{
135+
pfring_close(rxChannel);
136+
}
137+
}
138+
m_PfRingDescriptors.clear();
139+
}
140+
130141
bool PfRingDevice::setPfRingDeviceClock(pfring* ring)
131142
{
132143
struct timespec ltime;
@@ -153,6 +164,11 @@ namespace pcpp
153164
return false;
154165
}
155166

167+
if (numOfChannelIds < 0)
168+
{
169+
throw std::invalid_argument("numOfChannelIds must be >= 0");
170+
}
171+
156172
// I needed to add this verification because PF_RING doesn't provide it.
157173
// It allows opening the device on a channel that doesn't exist, but of course no packets will be captured
158174
uint8_t totalChannels = getTotalNumOfRxChannels();
@@ -167,8 +183,6 @@ namespace pcpp
167183
}
168184
}
169185

170-
m_NumOfOpenedRxChannels = 0;
171-
172186
for (int i = 0; i < numOfChannelIds; i++)
173187
{
174188
uint8_t channelId = channelIds[i];
@@ -177,12 +191,15 @@ namespace pcpp
177191
std::string ringName = ringNameStream.str();
178192
PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "] on channel [" << channelId
179193
<< "]. Channel name [" << ringName << "]");
180-
int res = openSingleRxChannel(ringName.c_str(), m_PfRingDescriptors[i]);
194+
195+
pfring* newChannel;
196+
int res = openSingleRxChannel(ringName.c_str(), newChannel);
181197
if (res == 0)
182198
{
199+
// Adds the newly opened channel to the list of opened channels
200+
m_PfRingDescriptors.push_back(newChannel);
183201
PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "] on channel [" << channelId
184202
<< "]. Channel name [" << ringName << "]");
185-
m_NumOfOpenedRxChannels++;
186203
continue;
187204
}
188205
else if (res == 1)
@@ -195,17 +212,12 @@ namespace pcpp
195212
break;
196213
}
197214

198-
if (m_NumOfOpenedRxChannels < numOfChannelIds)
215+
if (m_PfRingDescriptors.size() < static_cast<size_t>(numOfChannelIds))
199216
{
200217
// if an error occurred, close all rings from index=0 to index=m_NumOfOpenedRxChannels-1
201218
// there's no need to close m_PfRingDescriptors[m_NumOfOpenedRxChannels] because it has already been
202219
// closed by openSingleRxChannel
203-
for (int i = 0; i < m_NumOfOpenedRxChannels - 1; i++)
204-
{
205-
pfring_close(m_PfRingDescriptors[i]);
206-
}
207-
208-
m_NumOfOpenedRxChannels = 0;
220+
closeAllRxChannels();
209221
return false;
210222
}
211223

@@ -222,8 +234,6 @@ namespace pcpp
222234
return false;
223235
}
224236

225-
m_NumOfOpenedRxChannels = 0;
226-
227237
if (numOfRxChannelsToOpen > MAX_NUM_RX_CHANNELS)
228238
{
229239
PCPP_LOG_ERROR("Cannot open more than [" << MAX_NUM_RX_CHANNELS << "] channels");
@@ -240,7 +250,6 @@ namespace pcpp
240250

241251
cluster_type clusterType = (dist == RoundRobin) ? cluster_round_robin : cluster_per_flow;
242252

243-
int ringsOpen = 0;
244253
for (uint8_t channelId = 0; channelId < numOfRxChannelsOnNIC; channelId++)
245254
{
246255
// no more channels to open
@@ -253,44 +262,48 @@ namespace pcpp
253262
// open numOfRingsPerRxChannel rings per RX channel
254263
for (uint8_t ringId = 0; ringId < numOfRingsPerRxChannel; ringId++)
255264
{
256-
m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
257-
if (m_PfRingDescriptors[ringsOpen] == nullptr)
265+
pfring* newChannel = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
266+
if (newChannel == nullptr)
258267
{
259268
PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]");
260269
break;
261270
}
262271

263272
// setting a cluster for all rings in the same channel to enable hashing between them
264-
if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId + 1, clusterType) < 0)
273+
if (pfring_set_cluster(newChannel, channelId + 1, clusterType) < 0)
265274
{
266275
PCPP_LOG_ERROR("Couldn't set ring [" << (int)ringId << "] in channel [" << (int)channelId
267276
<< "] to the cluster [" << (int)(channelId + 1) << "]");
277+
pfring_close(newChannel); // Closes the ring as its initialization was not successful.
268278
break;
269279
}
270280

271-
ringsOpen++;
281+
// Assign the new channel to the list of opened channels
282+
m_PfRingDescriptors.push_back(newChannel);
272283
}
273284

274285
// open one more ring if remainder > 0
275286
if (remainderRings > 0)
276287
{
277-
m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
278-
if (m_PfRingDescriptors[ringsOpen] == nullptr)
288+
pfring* newChannel = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags);
289+
if (newChannel == nullptr)
279290
{
280291
PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]");
281292
break;
282293
}
283294

284295
// setting a cluster for all rings in the same channel to enable hashing between them
285-
if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId + 1, clusterType) < 0)
296+
if (pfring_set_cluster(newChannel, channelId + 1, clusterType) < 0)
286297
{
287298
PCPP_LOG_ERROR("Couldn't set ring [" << (int)(numOfRingsPerRxChannel + 1) << "] in channel ["
288299
<< (int)channelId << "] to the cluster ["
289300
<< (int)(channelId + 1) << "]");
301+
pfring_close(newChannel); // Closes the ring as its initialization was not successful.
290302
break;
291303
}
292304

293-
ringsOpen++;
305+
// Assign the new channel to the list of opened channels
306+
m_PfRingDescriptors.push_back(newChannel);
294307
remainderRings--;
295308
PCPP_LOG_DEBUG("Opened " << (int)(numOfRingsPerRxChannel + 1) << " rings on channel [" << (int)channelId
296309
<< "]");
@@ -300,44 +313,40 @@ namespace pcpp
300313
<< "]");
301314
}
302315

303-
if (ringsOpen < numOfRxChannelsToOpen)
316+
if (m_PfRingDescriptors.size() < numOfRxChannelsToOpen)
304317
{
305-
for (uint8_t i = 0; i < ringsOpen; i++)
306-
pfring_close(m_PfRingDescriptors[i]);
318+
closeAllRxChannels();
307319
return false;
308320
}
309321

310322
if (getIsHwClockEnable())
311323
{
312-
for (int i = 0; i < ringsOpen; i++)
324+
for (pfring* rxChannel : m_PfRingDescriptors)
313325
{
314-
if (setPfRingDeviceClock(m_PfRingDescriptors[i]))
326+
if (setPfRingDeviceClock(rxChannel))
315327
PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]");
316328
}
317329
}
318330

319331
// enable all rings
320-
for (int i = 0; i < ringsOpen; i++)
332+
for (size_t i = 0; i < m_PfRingDescriptors.size(); i++)
321333
{
322334
if (pfring_enable_rss_rehash(m_PfRingDescriptors[i]) < 0 || pfring_enable_ring(m_PfRingDescriptors[i]) < 0)
323335
{
324336
PCPP_LOG_ERROR("Unable to enable ring [" << i << "] for device [" << m_DeviceName << "]");
325337
// close all pfring's that were enabled until now
326-
for (int j = 0; j < ringsOpen; j++)
327-
pfring_close(m_PfRingDescriptors[j]);
338+
closeAllRxChannels(); // note: this function will clear the m_PfRingDescriptors vector
328339
return false;
329340
}
330341
}
331342

332-
m_NumOfOpenedRxChannels = ringsOpen;
333-
334343
m_DeviceOpened = true;
335344
return true;
336345
}
337346

338347
uint8_t PfRingDevice::getTotalNumOfRxChannels() const
339348
{
340-
if (m_NumOfOpenedRxChannels > 0)
349+
if (m_PfRingDescriptors.size() > 0)
341350
{
342351
uint8_t res = pfring_get_num_rx_channels(m_PfRingDescriptors[0]);
343352
return res;
@@ -365,9 +374,9 @@ namespace pcpp
365374
return false;
366375
}
367376

368-
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
377+
for (pfring* rxChannel : m_PfRingDescriptors)
369378
{
370-
int res = pfring_set_bpf_filter(m_PfRingDescriptors[i], (char*)filterAsString.c_str());
379+
int res = pfring_set_bpf_filter(rxChannel, (char*)filterAsString.c_str());
371380
if (res < 0)
372381
{
373382
if (res == PF_RING_ERROR_NOT_SUPPORTED)
@@ -390,9 +399,9 @@ namespace pcpp
390399
if (!m_IsFilterCurrentlySet)
391400
return true;
392401

393-
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
402+
for (pfring* rxChannel : m_PfRingDescriptors)
394403
{
395-
int res = pfring_remove_bpf_filter(m_PfRingDescriptors[i]);
404+
int res = pfring_remove_bpf_filter(rxChannel);
396405
if (res < 0)
397406
{
398407
PCPP_LOG_ERROR("Couldn't remove filter");
@@ -413,11 +422,9 @@ namespace pcpp
413422

414423
void PfRingDevice::close()
415424
{
416-
for (int i = 0; i < m_NumOfOpenedRxChannels; i++)
417-
pfring_close(m_PfRingDescriptors[i]);
425+
closeAllRxChannels();
418426
m_DeviceOpened = false;
419427
clearCoreConfiguration();
420-
m_NumOfOpenedRxChannels = 0;
421428
m_IsFilterCurrentlySet = false;
422429
PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] closed");
423430
}
@@ -461,10 +468,10 @@ namespace pcpp
461468
if (!initCoreConfigurationByCoreMask(coreMask))
462469
return false;
463470

464-
if (m_NumOfOpenedRxChannels != getCoresInUseCount())
471+
if (m_PfRingDescriptors.size() != getCoresInUseCount())
465472
{
466473
PCPP_LOG_ERROR("Cannot use a different number of channels and cores. Opened "
467-
<< m_NumOfOpenedRxChannels << " channels but set " << getCoresInUseCount()
474+
<< m_PfRingDescriptors.size() << " channels but set " << getCoresInUseCount()
468475
<< " cores in core mask");
469476
clearCoreConfiguration();
470477
return false;
@@ -530,7 +537,7 @@ namespace pcpp
530537
return false;
531538
}
532539

533-
if (m_NumOfOpenedRxChannels != 1)
540+
if (m_PfRingDescriptors.size() != 1)
534541
{
535542
PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX channel is opened");
536543
return false;
@@ -728,7 +735,7 @@ namespace pcpp
728735
config.clear();
729736
}
730737

731-
int PfRingDevice::getCoresInUseCount() const
738+
size_t PfRingDevice::getCoresInUseCount() const
732739
{
733740
return std::count_if(m_CoreConfiguration.begin(), m_CoreConfiguration.end(),
734741
[](const CoreConfiguration& config) { return config.IsInUse; });
@@ -741,7 +748,7 @@ namespace pcpp
741748

742749
pfring* ring = nullptr;
743750
bool closeRing = false;
744-
if (m_NumOfOpenedRxChannels > 0)
751+
if (m_PfRingDescriptors.size() > 0)
745752
ring = m_PfRingDescriptors[0];
746753
else
747754
{
@@ -884,8 +891,12 @@ namespace pcpp
884891
packetsSent++;
885892
}
886893

887-
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
888-
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
894+
// In case of failure due to closed device, there are not handles to flush.
895+
if (m_PfRingDescriptors.size() > 0)
896+
{
897+
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
898+
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
899+
}
889900

890901
PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " raw packets were sent successfully");
891902

@@ -904,8 +915,12 @@ namespace pcpp
904915
packetsSent++;
905916
}
906917

907-
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
908-
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
918+
// In case of failure due to closed device, there are not handles to flush.
919+
if (m_PfRingDescriptors.size() > 0)
920+
{
921+
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
922+
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
923+
}
909924

910925
PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " packets were sent successfully");
911926

@@ -923,8 +938,12 @@ namespace pcpp
923938
packetsSent++;
924939
}
925940

926-
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
927-
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
941+
// In case of failure due to closed device, there are not handles to flush.
942+
if (m_PfRingDescriptors.size() > 0)
943+
{
944+
// The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC
945+
pfring_flush_tx_packets(m_PfRingDescriptors[0]);
946+
}
928947

929948
PCPP_LOG_DEBUG(packetsSent << " out of " << rawPackets.size() << " raw packets were sent successfully");
930949

0 commit comments

Comments
 (0)