@@ -233,8 +233,9 @@ static __always_inline __u8 _ct_get_traffic_direction(__u8 observation_point) {
233233 * @arg key The key to be used to create the new connection.
234234 * @arg observation_point The point in the network stack where the packet is observed.
235235 * @arg is_reply true if the packet is a SYN-ACK packet. False if it is a SYN packet.
236+ * @arg sampled Whether or not the packet was sampled for reporting.
236237 */
237- static __always_inline bool _ct_create_new_tcp_connection (struct packet * p , struct ct_v4_key key , __u8 observation_point , bool is_reply ) {
238+ static __always_inline bool _ct_create_new_tcp_connection (struct packet * p , struct ct_v4_key key , __u8 observation_point , bool is_reply , bool sampled ) {
238239 struct ct_entry new_value ;
239240 __builtin_memset (& new_value , 0 , sizeof (struct ct_entry ));
240241 __u64 now = bpf_mono_now ();
@@ -245,14 +246,20 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
245246 new_value .eviction_time = now + CT_SYN_TIMEOUT ;
246247 if (is_reply ) {
247248 new_value .flags_seen_rx_dir = p -> flags ;
248- new_value .last_report_rx_dir = now ;
249- new_value .bytes_seen_since_last_report_rx_dir = 0 ;
250- new_value .packets_seen_since_last_report_rx_dir = 0 ;
249+ new_value .last_report_rx_dir = sampled ? now : 0 ;
250+ new_value .bytes_seen_since_last_report_rx_dir = !sampled ? p -> bytes : 0 ;
251+ new_value .packets_seen_since_last_report_rx_dir = !sampled ;
252+ if (!sampled ) {
253+ _ct_record_tcp_flags (p -> flags , & new_value .flags_seen_since_last_report_rx_dir );
254+ }
251255 } else {
252256 new_value .flags_seen_tx_dir = p -> flags ;
253- new_value .last_report_tx_dir = now ;
254- new_value .bytes_seen_since_last_report_tx_dir = 0 ;
255- new_value .packets_seen_since_last_report_tx_dir = 0 ;
257+ new_value .last_report_tx_dir = sampled ? now : 0 ;
258+ new_value .bytes_seen_since_last_report_tx_dir = !sampled ? p -> bytes : 0 ;
259+ new_value .packets_seen_since_last_report_tx_dir = !sampled ;
260+ if (!sampled ) {
261+ _ct_record_tcp_flags (p -> flags , & new_value .flags_seen_since_last_report_tx_dir );
262+ }
256263 }
257264 new_value .is_direction_unknown = false;
258265 new_value .traffic_direction = _ct_get_traffic_direction (observation_point );
@@ -273,16 +280,17 @@ static __always_inline bool _ct_create_new_tcp_connection(struct packet *p, stru
273280 p -> is_reply = is_reply ;
274281 p -> traffic_direction = new_value .traffic_direction ;
275282 bpf_map_update_elem (& retina_conntrack , & key , & new_value , BPF_ANY );
276- return true ;
283+ return sampled ;
277284}
278285
279286/**
280287 * Create a new UDP connection.
281288 * @arg *p pointer to the packet to be processed.
282289 * @arg key The key to be used to create the new connection.
283290 * @arg observation_point The point in the network stack where the packet is observed.
291+ * @arg sampled Whether or not the packet was sampled for reporting.
284292 */
285- static __always_inline bool _ct_handle_udp_connection (struct packet * p , struct ct_v4_key key , __u8 observation_point ) {
293+ static __always_inline bool _ct_handle_udp_connection (struct packet * p , struct ct_v4_key key , __u8 observation_point , bool sampled ) {
286294 struct ct_entry new_value ;
287295 __builtin_memset (& new_value , 0 , sizeof (struct ct_entry ));
288296 __u64 now = bpf_mono_now ();
@@ -292,9 +300,9 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
292300 }
293301 new_value .eviction_time = now + CT_CONNECTION_LIFETIME_NONTCP ;
294302 new_value .flags_seen_tx_dir = p -> flags ;
295- new_value .last_report_tx_dir = now ;
296- new_value .bytes_seen_since_last_report_tx_dir = 0 ;
297- new_value .packets_seen_since_last_report_tx_dir = 0 ;
303+ new_value .last_report_tx_dir = sampled ? now : 0 ;
304+ new_value .bytes_seen_since_last_report_tx_dir = ! sampled ? p -> bytes : 0 ;
305+ new_value .packets_seen_since_last_report_tx_dir = ! sampled ;
298306 new_value .traffic_direction = _ct_get_traffic_direction (observation_point );
299307 #ifdef ENABLE_CONNTRACK_METRICS
300308 new_value .conntrack_metadata .packets_tx_count = 1 ;
@@ -307,7 +315,7 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
307315 p -> is_reply = false;
308316 p -> traffic_direction = new_value .traffic_direction ;
309317 bpf_map_update_elem (& retina_conntrack , & key , & new_value , BPF_ANY );
310- return true ;
318+ return sampled ;
311319}
312320
313321/**
@@ -316,15 +324,16 @@ static __always_inline bool _ct_handle_udp_connection(struct packet *p, struct c
316324 * @arg key The key to be used to handle the connection.
317325 * @arg reverse_key The reverse key to be used to handle the connection.
318326 * @arg observation_point The point in the network stack where the packet is observed.
327+ * @arg sampled Whether or not the packet was sampled for reporting.
319328 */
320- static __always_inline bool _ct_handle_tcp_connection (struct packet * p , struct ct_v4_key key , struct ct_v4_key reverse_key , __u8 observation_point ) {
329+ static __always_inline bool _ct_handle_tcp_connection (struct packet * p , struct ct_v4_key key , struct ct_v4_key reverse_key , __u8 observation_point , bool sampled ) {
321330 u8 tcp_handshake = p -> flags & (TCP_SYN |TCP_ACK );
322331 if (tcp_handshake == TCP_SYN ) {
323332 // We have a SYN, we set `is_reply` to false and we provide `key`
324- return _ct_create_new_tcp_connection (p , key , observation_point , false);
333+ return _ct_create_new_tcp_connection (p , key , observation_point , false, sampled );
325334 } else if (tcp_handshake == TCP_SYN |TCP_ACK ) {
326335 // We have a SYN-ACK, we set `is_reply` to true and we provide `reverse_key`
327- return _ct_create_new_tcp_connection (p , reverse_key , observation_point , true);
336+ return _ct_create_new_tcp_connection (p , reverse_key , observation_point , true, sampled );
328337 }
329338
330339 // The packet is not a SYN packet and the connection corresponding to this packet is not found.
@@ -347,9 +356,12 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
347356 if (p -> flags & TCP_ACK ) {
348357 p -> is_reply = true;
349358 new_value .flags_seen_rx_dir = p -> flags ;
350- new_value .last_report_rx_dir = now ;
351- new_value .bytes_seen_since_last_report_rx_dir = 0 ;
352- new_value .packets_seen_since_last_report_rx_dir = 0 ;
359+ new_value .last_report_rx_dir = sampled ? now : 0 ;
360+ new_value .bytes_seen_since_last_report_rx_dir = !sampled ? p -> bytes : 0 ;
361+ new_value .packets_seen_since_last_report_rx_dir = !sampled ;
362+ if (!sampled ) {
363+ _ct_record_tcp_flags (p -> flags , & new_value .flags_seen_since_last_report_rx_dir );
364+ }
353365 #ifdef ENABLE_CONNTRACK_METRICS
354366 new_value .conntrack_metadata .bytes_rx_count = p -> bytes ;
355367 new_value .conntrack_metadata .packets_rx_count = 1 ;
@@ -358,9 +370,12 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
358370 } else { // Otherwise, the packet is considered as a packet in the send direction.
359371 p -> is_reply = false;
360372 new_value .flags_seen_tx_dir = p -> flags ;
361- new_value .last_report_tx_dir = now ;
362- new_value .bytes_seen_since_last_report_tx_dir = 0 ;
363- new_value .packets_seen_since_last_report_tx_dir = 0 ;
373+ new_value .last_report_tx_dir = sampled ? now : 0 ;
374+ new_value .bytes_seen_since_last_report_tx_dir = !sampled ? p -> bytes : 0 ;
375+ new_value .packets_seen_since_last_report_tx_dir = !sampled ;
376+ if (!sampled ) {
377+ _ct_record_tcp_flags (p -> flags , & new_value .flags_seen_since_last_report_tx_dir );
378+ }
364379 #ifdef ENABLE_CONNTRACK_METRICS
365380 new_value .conntrack_metadata .bytes_tx_count = p -> bytes ;
366381 new_value .conntrack_metadata .packets_tx_count = 1 ;
@@ -371,7 +386,7 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
371386 // Update packet's conntrack metadata.
372387 __builtin_memcpy (& p -> conntrack_metadata , & new_value .conntrack_metadata , sizeof (struct conntrackmetadata ));
373388 #endif // ENABLE_CONNTRACK_METRICS
374- return true ;
389+ return sampled ;
375390}
376391
377392/**
@@ -380,14 +395,15 @@ static __always_inline bool _ct_handle_tcp_connection(struct packet *p, struct c
380395 * @arg key The key to be used to handle the connection.
381396 * @arg reverse_key The reverse key to be used to handle the connection.
382397 * @arg observation_point The point in the network stack where the packet is observed.
398+ * @arg sampled Whether or not the packet was sampled for reporting.
383399 */
384- static __always_inline struct packetreport _ct_handle_new_connection (struct packet * p , struct ct_v4_key key , struct ct_v4_key reverse_key , __u8 observation_point ) {
400+ static __always_inline struct packetreport _ct_handle_new_connection (struct packet * p , struct ct_v4_key key , struct ct_v4_key reverse_key , __u8 observation_point , bool sampled ) {
385401 struct packetreport report ;
386402 __builtin_memset (& report , 0 , sizeof (struct packetreport ));
387403 if (key .proto & IPPROTO_TCP ) {
388- report .report = _ct_handle_tcp_connection (p , key , reverse_key , observation_point );
404+ report .report = _ct_handle_tcp_connection (p , key , reverse_key , observation_point , sampled );
389405 } else if (key .proto & IPPROTO_UDP ) {
390- report .report = _ct_handle_udp_connection (p , key , observation_point );
406+ report .report = _ct_handle_udp_connection (p , key , observation_point , sampled );
391407 } else {
392408 report .report = false; // We are not interested in other protocols.
393409 }
@@ -401,9 +417,10 @@ static __always_inline struct packetreport _ct_handle_new_connection(struct pack
401417 * @arg flags The flags of the packet.
402418 * @arg direction The direction of the packet in relation to the connection.
403419 * @arg bytes The size of the packet in bytes.
420+ * @arg sampled Whether or not the packet was sampled for reporting.
404421 * Returns a packetreport struct representing if the packet should be reported to userspace.
405422 */
406- static __always_inline struct packetreport _ct_should_report_packet (struct ct_v4_key * key , struct ct_entry * entry , __u8 flags , __u8 direction , __u32 bytes ) {
423+ static __always_inline struct packetreport _ct_should_report_packet (struct ct_v4_key * key , struct ct_entry * entry , __u8 flags , __u8 direction , __u32 bytes , bool sampled ) {
407424 struct packetreport report ;
408425 __builtin_memset (& report , 0 , sizeof (struct packetreport ));
409426 report .report = false;
@@ -513,21 +530,27 @@ static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4
513530 WRITE_ONCE (entry -> eviction_time , now + CT_CONNECTION_LIFETIME_NONTCP );
514531 }
515532
533+ if (flags != seen_flags ) {
534+ if (direction == CT_PACKET_DIR_TX ) {
535+ WRITE_ONCE (entry -> flags_seen_tx_dir , flags );
536+ } else {
537+ WRITE_ONCE (entry -> flags_seen_rx_dir , flags );
538+ }
539+ }
540+
516541 // Report if:
517542 // 1. We already decided to report based on protocol-specific rules, or
518- // 2. New flags have appeared, or
543+ // 2. New flags have appeared and the packet has been sampled , or
519544 // 3. Reporting interval has elapsed
520- if (should_report || flags != seen_flags || now - last_report >= CT_REPORT_INTERVAL ) {
545+ if (should_report || ( sampled && flags != seen_flags ) || now - last_report >= CT_REPORT_INTERVAL ) {
521546 report .report = true;
522547 // Update the connection's state
523548 if (direction == CT_PACKET_DIR_TX ) {
524- WRITE_ONCE (entry -> flags_seen_tx_dir , flags );
525549 WRITE_ONCE (entry -> last_report_tx_dir , now );
526550 WRITE_ONCE (entry -> bytes_seen_since_last_report_tx_dir , 0 );
527551 WRITE_ONCE (entry -> packets_seen_since_last_report_tx_dir , 0 );
528552 __builtin_memset (& entry -> flags_seen_since_last_report_tx_dir , 0 , sizeof (struct tcpflagscount ));
529553 } else {
530- WRITE_ONCE (entry -> flags_seen_rx_dir , flags );
531554 WRITE_ONCE (entry -> last_report_rx_dir , now );
532555 WRITE_ONCE (entry -> bytes_seen_since_last_report_rx_dir , 0 );
533556 WRITE_ONCE (entry -> packets_seen_since_last_report_rx_dir , 0 );
@@ -556,9 +579,10 @@ static __always_inline struct packetreport _ct_should_report_packet(struct ct_v4
556579 * Process a packet and update the connection tracking map.
557580 * @arg *p pointer to the packet to be processed.
558581 * @arg observation_point The point in the network stack where the packet is observed.
582+ * @arg sampled Whether or not the packet has been sampled for reporting.
559583 * Returns a packetreport struct representing if the packet should be reported to userspace.
560584 */
561- static __always_inline __attribute__((unused )) struct packetreport ct_process_packet (struct packet * p , __u8 observation_point ) {
585+ static __always_inline __attribute__((unused )) struct packetreport ct_process_packet (struct packet * p , __u8 observation_point , bool sampled ) {
562586 if (!p ) {
563587 struct packetreport report ;
564588 __builtin_memset (& report , 0 , sizeof (struct packetreport ));
@@ -592,7 +616,7 @@ static __always_inline __attribute__((unused)) struct packetreport ct_process_pa
592616 // Update packet's conntract metadata.
593617 __builtin_memcpy (& p -> conntrack_metadata , & entry -> conntrack_metadata , sizeof (struct conntrackmetadata ));
594618 #endif // ENABLE_CONNTRACK_METRICS
595- return _ct_should_report_packet (& key , entry , p -> flags , CT_PACKET_DIR_TX , p -> bytes );
619+ return _ct_should_report_packet (& key , entry , p -> flags , CT_PACKET_DIR_TX , p -> bytes , sampled );
596620 }
597621
598622 // The connection is not found in the send direction. Check the reply direction by reversing the key.
@@ -614,9 +638,9 @@ static __always_inline __attribute__((unused)) struct packetreport ct_process_pa
614638 // Update packet's conntract metadata.
615639 __builtin_memcpy (& p -> conntrack_metadata , & entry -> conntrack_metadata , sizeof (struct conntrackmetadata ));
616640 #endif // ENABLE_CONNTRACK_METRICS
617- return _ct_should_report_packet (& reverse_key , entry , p -> flags , CT_PACKET_DIR_RX , p -> bytes );
641+ return _ct_should_report_packet (& reverse_key , entry , p -> flags , CT_PACKET_DIR_RX , p -> bytes , sampled );
618642 }
619643
620644 // If the connection is still not found, the connection is new.
621- return _ct_handle_new_connection (p , key , reverse_key , observation_point );
622- }
645+ return _ct_handle_new_connection (p , key , reverse_key , observation_point , sampled );
646+ }
0 commit comments