@@ -169,24 +169,17 @@ void NHTFlowCache::push_to_export_queue(size_t flow_index) noexcept
169169
170170void NHTFlowCache::finish ()
171171{
172- /* auto it = std::find_if(m_hashes_in_ctt.begin(), m_hashes_in_ctt.end(), [](const auto& pair) {
173- return pair.second <= 0;
174- });*/
175- for (decltype (m_cache_size) i = 0 ; i < m_cache_size; i++) {
176- if (!m_flow_table[i]->is_empty ()) {
172+ std::for_each_n (m_flow_table.begin (), m_cache_size, [this ](FlowRecord*& flow_record) {
173+ if (!flow_record->is_empty ()) {
177174#ifdef WITH_CTT
178- if (m_flow_table[i] ->is_in_ctt && !m_flow_table[i] ->is_waiting_for_export ) {
179- send_export_request_to_ctt (m_flow_table[i] ->m_flow .flow_hash_ctt );
175+ if (flow_record ->is_in_ctt && !flow_record ->is_waiting_for_export ) {
176+ m_ctt_controller-> remove_record_without_notification (flow_record ->m_flow .flow_hash_ctt );
180177 }
181178#endif /* WITH_CTT */
182- plugins_pre_export (m_flow_table[i] ->m_flow );
183- export_flow (i , FLOW_END_FORCED);
179+ plugins_pre_export (flow_record ->m_flow );
180+ export_flow (flow_record-> m_flow . flow_hash , FLOW_END_FORCED);
184181 }
185- }
186- /* if (m_hashes_in_ctt.size() > 0){
187- throw "bad CTT size";
188- }
189- std::cout << "CTT hash collisions: " << m_ctt_hash_collision << std::endl;*/
182+ });
190183}
191184
192185void NHTFlowCache::flush (Packet &pkt, size_t flow_index, int return_flags)
@@ -195,10 +188,10 @@ void NHTFlowCache::flush(Packet &pkt, size_t flow_index, int return_flags)
195188
196189 if (return_flags == ProcessPlugin::FlowAction::FLUSH_WITH_REINSERT) {
197190#ifdef WITH_CTT
198- if (m_flow_table[flow_index]->is_in_ctt && !m_flow_table[flow_index]->is_waiting_for_export ) {
191+ /* if (m_flow_table[flow_index]->is_in_ctt && !m_flow_table[flow_index]->is_waiting_for_export) {
199192 m_flow_table[flow_index]->is_waiting_for_export = true;
200- send_export_request_to_ctt (m_flow_table[flow_index]->m_flow .flow_hash_ctt );
201- }
193+ m_ctt_controller->remove_record_without_notification (m_flow_table[flow_index]->m_flow.flow_hash_ctt);
194+ }*/
202195#endif /* WITH_CTT */
203196 push_to_export_queue (flow_index);
204197 m_flow_table[flow_index]->m_flow .remove_extensions ();
@@ -293,19 +286,10 @@ void NHTFlowCache::create_record(const Packet& packet, size_t flow_index, size_t
293286 }
294287 m_flow_table[flow_index]->m_flow .flow_hash_ctt = packet.cttmeta .flow_hash ;
295288 if (needs_to_be_offloaded (flow_index)) {
296- /* m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt]++;
297- if (m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt] >= 2) {
298- m_ctt_hash_collision++;
299- std::vector<FlowRecord*> filtered;
300-
301- std::copy_if(m_flow_table.begin(), m_flow_table.end(), std::back_inserter(filtered),
302- [&](FlowRecord* flow) { return flow->m_flow.flow_hash_ctt == m_flow_table[flow_index]->m_flow.flow_hash_ctt; });
303- filtered.size();
304- }
305- auto x = m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt];*/
306- m_ctt_controller->create_record (m_flow_table[flow_index]->m_flow , m_dma_channel);
289+ m_ctt_controller->create_record (m_flow_table[flow_index]->m_flow , m_dma_channel, OffloadMode::TRIMMED_PACKET_WITH_METADATA_AND_EXPORT);
307290 m_ctt_stats.flows_offloaded ++;
308291 m_flow_table[flow_index]->is_in_ctt = true ;
292+ m_flow_table[flow_index]->offload_mode = OffloadMode::TRIMMED_PACKET_WITH_METADATA_AND_EXPORT;
309293 }
310294#endif /* WITH_CTT */
311295}
@@ -317,19 +301,10 @@ void NHTFlowCache::try_to_add_flow_to_ctt(size_t flow_index) noexcept
317301 return ;
318302 }
319303 if (needs_to_be_offloaded (flow_index)) {
320- /* m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt]++;
321- auto x = m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt];
322- if (m_hashes_in_ctt[m_flow_table[flow_index]->m_flow.flow_hash_ctt] >= 2) {
323- m_ctt_hash_collision++;
324- std::vector<FlowRecord*> filtered;
325-
326- std::copy_if(m_flow_table.begin(), m_flow_table.end(), std::back_inserter(filtered),
327- [&](FlowRecord* flow) { return flow->m_flow.flow_hash_ctt == m_flow_table[flow_index]->m_flow.flow_hash_ctt; });
328- filtered.size();
329- }*/
330- m_ctt_controller->create_record (m_flow_table[flow_index]->m_flow , m_dma_channel);
304+ m_ctt_controller->create_record (m_flow_table[flow_index]->m_flow , m_dma_channel, OffloadMode::TRIMMED_PACKET_WITH_METADATA_AND_EXPORT);
331305 m_ctt_stats.flows_offloaded ++;
332306 m_flow_table[flow_index]->is_in_ctt = true ;
307+ m_flow_table[flow_index]->offload_mode = OffloadMode::TRIMMED_PACKET_WITH_METADATA_AND_EXPORT;
333308 }
334309}
335310#endif /* WITH_CTT */
@@ -399,13 +374,6 @@ bool NHTFlowCache::try_to_export(size_t flow_index, bool call_pre_export, const
399374#ifdef WITH_CTT
400375void NHTFlowCache::send_export_request_to_ctt (size_t ctt_flow_hash) noexcept
401376{
402- /* if (--m_hashes_in_ctt[ctt_flow_hash] < 0)
403- {
404- throw "missing hash in send_export_request_to_ctt!";
405- }
406- if (m_hashes_in_ctt[ctt_flow_hash] == 0) {
407- m_hashes_in_ctt.erase(ctt_flow_hash);
408- }*/
409377 m_ctt_controller->export_record (ctt_flow_hash);
410378}
411379#endif /* WITH_CTT */
@@ -416,7 +384,7 @@ bool NHTFlowCache::try_to_export(size_t flow_index, bool call_pre_export, const
416384 if (m_flow_table[flow_index]->is_in_ctt ) {
417385 if (!m_flow_table[flow_index]->is_waiting_for_export ) {
418386 m_flow_table[flow_index]->is_waiting_for_export = true ;
419- send_export_request_to_ctt (m_flow_table[flow_index]->m_flow .flow_hash_ctt );
387+ m_ctt_controller-> export_record (m_flow_table[flow_index]->m_flow .flow_hash_ctt );
420388 m_flow_table[flow_index]->export_time = {now.tv_sec + 1 , now.tv_usec };
421389 return false ;
422390 }
@@ -483,29 +451,49 @@ void NHTFlowCache::update_ctt_export_stats(CttExportReason ctt_reason, Managemen
483451 }
484452}
485453
454+ static bool is_counter_overflow (CttExportReason ctt_reason, ManagementUnitExportReason mu_reason) noexcept
455+ {
456+ return ctt_reason == CttExportReason::MANAGEMENT_UNIT && (mu_reason & ManagementUnitExportReason::COUNTER_OVERFLOW);
457+ }
458+
486459void NHTFlowCache::export_external (const Packet& pkt) noexcept
487460{
488461 m_ctt_stats.export_packets ++;
489- std::optional<CttExport> export_data = CttExport::parse (pkt.packet , pkt.packet_len );
462+ const std::optional<CttExport> export_data = CttExport::parse (pkt.packet , pkt.packet_len );
490463 if (!export_data.has_value ()) {
491464 m_ctt_stats.export_packets_parsing_failed ++;
492465 return ;
493466 }
494467
495- IP ip_version = export_data->state .ip_version == 0 ? IP::v4 : IP::v6;
468+ const IP ip_version = export_data->state .ip_version == 0 ? IP::v4 : IP::v6;
496469 std::variant<FlowKeyv4, FlowKeyv6> key = *FlowKeyFactory::create_direct_key (&export_data->state .src_ip , &export_data->state .dst_ip ,
497470 export_data->state .src_port , export_data->state .dst_port , export_data->state .ip_proto , ip_version);
471+ // CTT keeps ip addresses in LE
498472 std::visit ([](auto & key) {
499473 std::reverse (key.src_ip .data (), key.src_ip .data () + sizeof (key.src_ip ));
500474 std::reverse (key.dst_ip .data (), key.dst_ip .data () + sizeof (key.dst_ip ));
501475 }, key);
502476 const auto [row, flow_index, hash_value] = find_row (key);
503- if (!flow_index.has_value ()) {
477+ if (!flow_index.has_value ()
478+ || !m_flow_table[flow_index.value ()]->is_in_ctt
479+ || !m_flow_table[flow_index.value ()]->offload_mode .has_value ())
504480 m_ctt_stats.export_packets_for_missing_flow ++;
505481 return ;
506482 }
507483
508484 update_ctt_export_stats (export_data->reason, export_data->mu_reason);
485+
486+ if ((is_counter_overflow(export_data->reason, export_data->mu_reason)) {
487+ if (m_flow_table[flow_index.value ()]->offload_mode == OffloadMode::TRIMMED_PACKET_WITH_METADATA_AND_EXPORT) {
488+ return ;
489+ }
490+ }
491+ if (export_data->reason == CttExportReason::CTT_FULL) {
492+ m_flow_table[flow_index.value ()]->is_in_ctt = false ;
493+ m_flow_table[flow_index.value ()]->is_waiting_for_export = false ;
494+ m_flow_table[flow_index.value ()]->offload_mode = std::nullopt ;
495+ }
496+
509497 export_flow (flow_index.value(), convert_ctt_export_reason_to_ipfxiprobe(export_data->reason, export_data->mu_reason));
510498 m_ctt_stats.flows_removed++;
511499}
@@ -581,7 +569,7 @@ int NHTFlowCache::put_pkt(Packet& packet)
581569#ifdef WITH_CTT
582570 if (m_flow_table[flow_index]->is_in_ctt && !m_flow_table[flow_index]->is_waiting_for_export ) {
583571 m_flow_table[flow_index]->is_waiting_for_export = true ;
584- send_export_request_to_ctt (m_flow_table[flow_index]->m_flow .flow_hash_ctt );
572+ remove_record_without_notification (m_flow_table[flow_index]->m_flow .flow_hash_ctt );
585573 m_flow_table[flow_index]->export_time = {packet.ts .tv_sec + 1 , packet.ts .tv_usec };
586574 }
587575#endif /* WITH_CTT */
0 commit comments