1010#include "utils.h"
1111#include "maps_definition.h"
1212
13- static __always_inline void fill_flow_seq_id (flow_seq_id * seq_id , pkt_info * pkt , u32 seq , u8 reversed ) {
13+ const u64 MIN_RTT = 50000 ; //50 micro seconds
14+
15+ static __always_inline void fill_flow_seq_id (flow_seq_id * seq_id , pkt_info * pkt , u32 seq , bool reverse ) {
1416 flow_id * id = pkt -> id ;
15- if (reversed ) {
17+ if (reverse ) {
1618 __builtin_memcpy (seq_id -> src_ip , id -> dst_ip , IP_MAX_LEN );
1719 __builtin_memcpy (seq_id -> dst_ip , id -> src_ip , IP_MAX_LEN );
1820 seq_id -> src_port = id -> dst_port ;
@@ -23,49 +25,104 @@ static __always_inline void fill_flow_seq_id(flow_seq_id *seq_id, pkt_info *pkt,
2325 seq_id -> src_port = id -> src_port ;
2426 seq_id -> dst_port = id -> dst_port ;
2527 }
28+ seq_id -> transport_protocol = id -> transport_protocol ;
2629 seq_id -> seq_id = seq ;
30+ seq_id -> if_index = id -> if_index ;
2731}
2832
29- static __always_inline void calculate_flow_rtt_tcp (pkt_info * pkt , u8 direction , void * data_end , flow_seq_id * seq_id ) {
30- struct tcphdr * tcp = (struct tcphdr * ) pkt -> l4_hdr ;
31- if ( !tcp || ((void * )tcp + sizeof (* tcp ) > data_end ) ) {
32- return ;
33- }
33+ static __always_inline void reverse_flow_id_struct (flow_id * src , flow_id * dst ) {
34+ // Fields which remain same
35+ dst -> eth_protocol = src -> eth_protocol ;
36+ dst -> transport_protocol = src -> transport_protocol ;
37+ dst -> if_index = src -> if_index ;
38+
39+ // Fields which should be reversed
40+ dst -> direction = (src -> direction == INGRESS ) ? EGRESS : INGRESS ;
41+ __builtin_memcpy (dst -> src_mac , src -> dst_mac , ETH_ALEN );
42+ __builtin_memcpy (dst -> dst_mac , src -> src_mac , ETH_ALEN );
43+ __builtin_memcpy (dst -> src_ip , src -> dst_ip , IP_MAX_LEN );
44+ __builtin_memcpy (dst -> dst_ip , src -> src_ip , IP_MAX_LEN );
45+ dst -> src_port = src -> dst_port ;
46+ dst -> dst_port = src -> src_port ;
47+ /* ICMP type can be ignore for now. We only deal with TCP packets for now.*/
48+ }
3449
35- switch (direction ) {
36- case EGRESS : {
37- if (IS_SYN_PACKET (pkt )) {
38- // Record the outgoing syn sequence number
39- u32 seq = bpf_ntohl (tcp -> seq );
40- fill_flow_seq_id (seq_id , pkt , seq , 0 );
50+ static __always_inline void update_reverse_flow_rtt (pkt_info * pkt , u32 seq ) {
51+ flow_id rev_flow_id ;
52+ __builtin_memset (& rev_flow_id , 0 , sizeof (rev_flow_id ));
53+ reverse_flow_id_struct (pkt -> id , & rev_flow_id );
4154
42- long ret = bpf_map_update_elem (& flow_sequences , seq_id , & pkt -> current_ts , BPF_ANY );
55+ flow_metrics * reverse_flow = (flow_metrics * )bpf_map_lookup_elem (& aggregated_flows , & rev_flow_id );
56+ if (reverse_flow != NULL ) {
57+ if (pkt -> rtt > reverse_flow -> flow_rtt ) {
58+ reverse_flow -> flow_rtt = pkt -> rtt ;
59+ long ret = bpf_map_update_elem (& aggregated_flows , & rev_flow_id , reverse_flow , BPF_EXIST );
4360 if (trace_messages && ret != 0 ) {
44- bpf_printk ("err saving flow sequence record %d " , ret );
61+ bpf_printk ("error updating rtt value in flow %d\n " , ret );
4562 }
4663 }
47- break ;
4864 }
49- case INGRESS : {
50- if (IS_ACK_PACKET (pkt )) {
51- // Stored sequence should be ack_seq - 1
52- u32 seq = bpf_ntohl (tcp -> ack_seq ) - 1 ;
53- // check reversed flow
54- fill_flow_seq_id (seq_id , pkt , seq , 1 );
55-
56- u64 * prev_ts = (u64 * )bpf_map_lookup_elem (& flow_sequences , seq_id );
57- if (prev_ts != NULL ) {
58- pkt -> rtt = pkt -> current_ts - * prev_ts ;
59- // Delete the flow from flow sequence map so if it
60- // restarts we have a new RTT calculation.
61- long ret = bpf_map_delete_elem (& flow_sequences , seq_id );
62- if (trace_messages && ret != 0 ) {
63- bpf_printk ("error evicting flow sequence: %d" , ret );
64- }
65- }
65+ }
66+
67+ static __always_inline void __calculate_tcp_rtt (pkt_info * pkt , struct tcphdr * tcp , flow_seq_id * seq_id ) {
68+ // Stored sequence should be ack_seq - 1
69+ u32 seq = bpf_ntohl (tcp -> ack_seq ) - 1 ;
70+ // check reversed flow
71+ fill_flow_seq_id (seq_id , pkt , seq , true);
72+
73+ u64 * prev_ts = (u64 * )bpf_map_lookup_elem (& flow_sequences , seq_id );
74+ if (prev_ts != NULL ) {
75+ u64 rtt = pkt -> current_ts - * prev_ts ;
76+ /**
77+ * FIXME: Because of SAMPLING the way it is done if we miss one of SYN/SYN+ACK/ACK
78+ * then we can get RTT values which are the process response time rather than actual RTT.
79+ * This check below clears them out but needs to be modified with a better solution or change
80+ * the algorithm for calculating RTT so it doesn't interact with SAMPLING like this.
81+ */
82+ if (rtt < MIN_RTT ) {
83+ return ;
6684 }
67- break ;
85+ pkt -> rtt = rtt ;
86+ // Delete the flow from flow sequence map so if it
87+ // restarts we have a new RTT calculation.
88+ long ret = bpf_map_delete_elem (& flow_sequences , seq_id );
89+ if (trace_messages && ret != 0 ) {
90+ bpf_printk ("error evicting flow sequence: %d" , ret );
91+ }
92+ // This is an ACK packet with valid sequence id so a SYN must
93+ // have been sent. We can safely update the reverse flow RTT here.
94+ update_reverse_flow_rtt (pkt , seq );
6895 }
96+ return ;
97+ }
98+
99+ static __always_inline void __store_tcp_ts (pkt_info * pkt , struct tcphdr * tcp , flow_seq_id * seq_id ) {
100+ // store timestamp of syn packets.
101+ u32 seq = bpf_ntohl (tcp -> seq );
102+ fill_flow_seq_id (seq_id , pkt , seq , false);
103+ long ret = bpf_map_update_elem (& flow_sequences , seq_id , & pkt -> current_ts , BPF_NOEXIST );
104+ if (trace_messages && ret != 0 ) {
105+ bpf_printk ("err saving flow sequence record %d" , ret );
106+ }
107+ return ;
108+ }
109+
110+ static __always_inline void calculate_flow_rtt_tcp (pkt_info * pkt , u8 direction , void * data_end , flow_seq_id * seq_id ) {
111+ struct tcphdr * tcp = (struct tcphdr * ) pkt -> l4_hdr ;
112+ if ( !tcp || ((void * )tcp + sizeof (* tcp ) > data_end ) ) {
113+ return ;
114+ }
115+
116+ /* We calculate RTT for both SYN/SYN+ACK and SYN+ACK/ACK and take the maximum of both.*/
117+ if (tcp -> syn && tcp -> ack ) { // SYN ACK Packet
118+ __calculate_tcp_rtt (pkt , tcp , seq_id );
119+ __store_tcp_ts (pkt , tcp , seq_id );
120+ }
121+ else if (tcp -> ack ) {
122+ __calculate_tcp_rtt (pkt , tcp , seq_id );
123+ }
124+ else if (tcp -> syn ) {
125+ __store_tcp_ts (pkt , tcp , seq_id );
69126 }
70127}
71128
@@ -83,5 +140,4 @@ static __always_inline void calculate_flow_rtt(pkt_info *pkt, u8 direction, void
83140 }
84141}
85142
86- #endif /* __RTT_TRACKER_H__ */
87-
143+ #endif /* __RTT_TRACKER_H__ */
0 commit comments