@@ -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