added rtt and rtt deviation calculation for the tcp layer

This commit is contained in:
cozis
2023-08-29 12:56:23 +02:00
parent 6bfb514df7
commit 91f2526f15
10 changed files with 87 additions and 35 deletions
+3 -1
View File
@@ -223,8 +223,10 @@ static void arp_translation_table_seconds_passed(arp_translation_table_t *table,
} }
} }
void arp_seconds_passed(arp_state_t *state, size_t seconds) void arp_ms_passed(arp_state_t *state, size_t ms)
{ {
size_t seconds = ms / 1000;
state->time += seconds; state->time += seconds;
// Scan through all of the timed-out entries // Scan through all of the timed-out entries
+1 -1
View File
@@ -124,5 +124,5 @@ void arp_resolve_mac(arp_state_t *state,
void *userp, void *userp,
void (*callback)(void*, arp_resolution_status_t, mac_address_t)); void (*callback)(void*, arp_resolution_status_t, mac_address_t));
void arp_seconds_passed(arp_state_t *state, size_t seconds); void arp_ms_passed(arp_state_t *state, size_t ms);
void arp_change_output_buffer(arp_state_t *state, void *ptr, size_t max); void arp_change_output_buffer(arp_state_t *state, void *ptr, size_t max);
+1
View File
@@ -22,5 +22,6 @@ typedef struct {
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
#define ABS(X) ((X) < 0 ? -(X) : (X))
#endif /* MICROTCP_DEFS_H */ #endif /* MICROTCP_DEFS_H */
+2 -3
View File
@@ -29,7 +29,6 @@ static uint16_t calculate_checksum_ip(const void *src, size_t len)
return cpu_to_net_u16(~sum); return cpu_to_net_u16(~sum);
} }
static ip_plugged_protocol_t * static ip_plugged_protocol_t *
find_protocol_with_id(ip_state_t *ip_state, uint8_t protocol) find_protocol_with_id(ip_state_t *ip_state, uint8_t protocol)
{ {
@@ -125,10 +124,10 @@ void ip_change_output_buffer(ip_state_t *state, void *ptr, size_t max)
icmp_change_output_buffer(&state->icmp_state, (ip_packet_t*) ptr + 1, max - sizeof(ip_packet_t)); icmp_change_output_buffer(&state->icmp_state, (ip_packet_t*) ptr + 1, max - sizeof(ip_packet_t));
} }
void ip_seconds_passed(ip_state_t *state, size_t seconds) void ip_ms_passed(ip_state_t *state, size_t ms)
{ {
(void) state; (void) state;
(void) seconds; (void) ms;
} }
int ip_send(ip_state_t *state, ip_protocol_t protocol, int ip_send(ip_state_t *state, ip_protocol_t protocol,
+1 -1
View File
@@ -54,7 +54,7 @@ typedef struct {
ip_plugged_protocol_t plugged_protocols[IP_PLUGGED_PROTOCOLS_MAX]; ip_plugged_protocol_t plugged_protocols[IP_PLUGGED_PROTOCOLS_MAX];
} ip_state_t; } ip_state_t;
void ip_seconds_passed(ip_state_t *state, size_t seconds); void ip_ms_passed(ip_state_t *state, size_t ms);
void ip_change_output_buffer(ip_state_t *state, void *ptr, size_t max); void ip_change_output_buffer(ip_state_t *state, void *ptr, size_t max);
void ip_init(ip_state_t *state, ip_address_t ip, void *send_data, void (*send)(void*, ip_address_t, size_t)); void ip_init(ip_state_t *state, ip_address_t ip, void *send_data, void (*send)(void*, ip_address_t, size_t));
void ip_free(ip_state_t *state); void ip_free(ip_state_t *state);
+18 -9
View File
@@ -105,7 +105,7 @@ struct microtcp_socket_t {
struct microtcp_t { struct microtcp_t {
time_t last_update_time; uint64_t last_update_time_ms;
#ifdef MICROTCP_BACKGROUND_THREAD #ifdef MICROTCP_BACKGROUND_THREAD
bool thread_should_stop; bool thread_should_stop;
@@ -396,6 +396,13 @@ void microtcp_process_packet(microtcp_t *mtcp, const void *packet, size_t len)
UNLOCK_WHEN_THREADED(mtcp); UNLOCK_WHEN_THREADED(mtcp);
} }
static uint64_t get_time_in_ms(void)
{
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec * 1000 + t.tv_nsec / 1000000;
}
void microtcp_step(microtcp_t *mtcp) void microtcp_step(microtcp_t *mtcp)
{ {
char packet[1024]; // This buffer is the bottleneck for the char packet[1024]; // This buffer is the bottleneck for the
@@ -408,18 +415,20 @@ void microtcp_step(microtcp_t *mtcp)
if (size < 0) if (size < 0)
return; return;
uint64_t current_time_ms = get_time_in_ms();
fprintf(stderr, "current_time_ms=%lld\n", current_time_ms);
LOCK_WHEN_THREADED(mtcp); LOCK_WHEN_THREADED(mtcp);
{ {
process_packet(mtcp, packet, size); process_packet(mtcp, packet, size);
time_t current_time = time(NULL); uint64_t ms = (current_time_ms - mtcp->last_update_time_ms);
int secs = (float) (current_time - mtcp->last_update_time);
if (secs > 0) { if (ms > 0) {
ip_seconds_passed(&mtcp->ip_state, secs); ip_ms_passed(&mtcp->ip_state, ms);
arp_seconds_passed(&mtcp->arp_state, secs); arp_ms_passed(&mtcp->arp_state, ms);
tcp_seconds_passed(&mtcp->tcp_state, secs); tcp_ms_passed(&mtcp->tcp_state, ms);
mtcp->last_update_time = current_time; mtcp->last_update_time_ms = current_time_ms;
} }
} }
UNLOCK_WHEN_THREADED(mtcp); UNLOCK_WHEN_THREADED(mtcp);
@@ -458,7 +467,7 @@ microtcp_t *microtcp_create_using_callbacks(const char *ip, const char *mac,
mtcp->ip = parsed_ip; mtcp->ip = parsed_ip;
mtcp->mac = parsed_mac; mtcp->mac = parsed_mac;
mtcp->callbacks = callbacks; mtcp->callbacks = callbacks;
mtcp->last_update_time = time(NULL); mtcp->last_update_time_ms = get_time_in_ms();
mtcp->used_buffer = NULL; mtcp->used_buffer = NULL;
mtcp->wait_buffer_list = NULL; mtcp->wait_buffer_list = NULL;
+40 -6
View File
@@ -42,9 +42,9 @@ void tcp_free(tcp_state_t *state)
tcp_timerset_free(&state->timers); tcp_timerset_free(&state->timers);
} }
void tcp_seconds_passed(tcp_state_t *state, size_t seconds) void tcp_ms_passed(tcp_state_t *state, size_t ms)
{ {
tcp_timerset_step(&state->timers, seconds); tcp_timerset_step(&state->timers, ms);
} }
static tcp_connection_t* static tcp_connection_t*
@@ -74,6 +74,13 @@ connection_create(tcp_listener_t *listener,
connection->state = TCP_STATE_CLOSED; connection->state = TCP_STATE_CLOSED;
connection->rtt = 0;
connection->dev_rtt = 0;
connection->calculating_rtt = false;
connection->rtt_calc_seq = 0;
connection->rtt_calc_time = 0;
connection->peer_port = peer_port; connection->peer_port = peer_port;
connection->peer_ip = peer_ip; connection->peer_ip = peer_ip;
@@ -110,7 +117,7 @@ find_listener_with_port(tcp_state_t *state, uint16_t port)
return NULL; return NULL;
} }
static uint32_t choose_sequence_no() static uint32_t choose_sequence_no(void)
{ {
return 0; return 0;
} }
@@ -222,6 +229,11 @@ static void emit_segment(tcp_connection_t *connection, uint8_t flags, size_t pay
} }
} }
if (!connection->calculating_rtt) {
connection->calculating_rtt = true;
connection->rtt_calc_seq = connection->snd_nxt; // -1?
connection->rtt_calc_time = connection->listener->state->timers.current_time_ms;
}
} }
static void handle_received_data(tcp_connection_t *connection, static void handle_received_data(tcp_connection_t *connection,
@@ -331,10 +343,30 @@ static bool ack_until(tcp_connection_t *connection, uint32_t ack_no)
} }
size_t newly_acked_bytes = ack_no - connection->snd_una; size_t newly_acked_bytes = ack_no - connection->snd_una;
if (ack_no > 1) { // Only remove data from the output buffer when
// the acked data wasn't a ghost byte
memmove(connection->out_buffer, connection->out_buffer + newly_acked_bytes, connection->snd_wnd - newly_acked_bytes); memmove(connection->out_buffer, connection->out_buffer + newly_acked_bytes, connection->snd_wnd - newly_acked_bytes);
connection->snd_wnd -= newly_acked_bytes; connection->snd_wnd -= newly_acked_bytes;
}
connection->snd_una = ack_no; connection->snd_una = ack_no;
TCP_DEBUG_LOG("calculating_rtt=%s, ack_no=%d, calc_seq=%d", connection->calculating_rtt ? "true" : "false", ack_no, connection->rtt_calc_seq);
if (connection->calculating_rtt) {
if (ack_no >= connection->rtt_calc_seq) {
uint64_t rtt = connection->listener->state->timers.current_time_ms - connection->rtt_calc_time;
TCP_DEBUG_LOG("Estimated RTT=%lld", rtt);
float w1 = 0.9;
float w2 = 0.125;
connection->rtt = w1 * rtt + (1-w1) * connection->rtt;
connection->dev_rtt = w2 * ABS((int) rtt - (int) connection->rtt) + (1-w2) * connection->dev_rtt;
connection->calculating_rtt = false;
}
}
return true; return true;
} }
@@ -519,6 +551,9 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
TCP_DEBUG_LOG("Connection request handled"); TCP_DEBUG_LOG("Connection request handled");
} else { } else {
TCP_DEBUG_LOG("RTT=%lld, DevRTT=%lld", connection->rtt, connection->dev_rtt);
// Something sent to an already instanciated // Something sent to an already instanciated
// connection. Since there is an instance, it // connection. Since there is an instance, it
// means that at least the first SYN was received // means that at least the first SYN was received
@@ -560,7 +595,8 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender,
"the peer will retransmit it"); "the peer will retransmit it");
// The connection is now established. // The connection is now established.
connection->snd_una = net_to_cpu_u32(segment->ack_no); uint32_t ack_no = net_to_cpu_u32(segment->ack_no);
ack_until(connection, ack_no);
connection->state = TCP_STATE_ESTAB; connection->state = TCP_STATE_ESTAB;
move_from_non_established_list_to_non_accepted_queue(connection); move_from_non_established_list_to_non_accepted_queue(connection);
@@ -747,8 +783,6 @@ tcp_connection_t *tcp_listener_accept(tcp_listener_t *listener, void *callback_d
void (*callback_ready_to_recv)(void*), void (*callback_ready_to_recv)(void*),
void (*callback_ready_to_send)(void*)) void (*callback_ready_to_send)(void*))
{ {
(void) listener;
if (!listener->non_accepted_queue_head) if (!listener->non_accepted_queue_head)
// Nothing to accept // Nothing to accept
return NULL; return NULL;
+9 -2
View File
@@ -6,7 +6,7 @@
#include "tcp_timer.h" #include "tcp_timer.h"
#endif #endif
#define TCP_TIMEOUT_TIME_WAIT 240 #define TCP_TIMEOUT_TIME_WAIT 240000
#define TCP_MAX_TIMEOUTS 1024 #define TCP_MAX_TIMEOUTS 1024
#define TCP_MAX_LISTENERS 32 #define TCP_MAX_LISTENERS 32
@@ -88,6 +88,13 @@ struct tcp_connection_t {
ip_address_t peer_ip; // Network byte order ip_address_t peer_ip; // Network byte order
uint16_t peer_port; // CPU byte order uint16_t peer_port; // CPU byte order
uint64_t rtt;
uint64_t dev_rtt;
bool calculating_rtt;
uint32_t rtt_calc_seq;
uint64_t rtt_calc_time;
// Send Sequence Space // Send Sequence Space
// //
// 1 2 3 4 // 1 2 3 4
@@ -166,7 +173,7 @@ struct tcp_state_t {
void tcp_init(tcp_state_t *tcp_state, ip_address_t ip, tcp_callbacks_t callbacks); void tcp_init(tcp_state_t *tcp_state, ip_address_t ip, tcp_callbacks_t callbacks);
void tcp_free(tcp_state_t *tcp_state); void tcp_free(tcp_state_t *tcp_state);
void tcp_seconds_passed(tcp_state_t *state, size_t seconds); void tcp_ms_passed(tcp_state_t *state, size_t ms);
void tcp_process_segment(tcp_state_t *state, ip_address_t sender, tcp_segment_t *segment, size_t len); void tcp_process_segment(tcp_state_t *state, ip_address_t sender, tcp_segment_t *segment, size_t len);
tcp_listener_t *tcp_listener_create(tcp_state_t *state, uint16_t port, bool reuse, void *data, void (*callback)(void*)); tcp_listener_t *tcp_listener_create(tcp_state_t *state, uint16_t port, bool reuse, void *data, void (*callback)(void*));
void tcp_listener_destroy(tcp_listener_t *listener); void tcp_listener_destroy(tcp_listener_t *listener);
+6 -6
View File
@@ -41,7 +41,7 @@ void tcp_timer_disable(tcp_timer_t *timer)
set->free_list = timer; set->free_list = timer;
} }
tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t seconds, tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t ms,
void (*callback)(void*), void *data) void (*callback)(void*), void *data)
{ {
assert(callback); assert(callback);
@@ -58,7 +58,7 @@ tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t seconds,
// first item of the free list. // first item of the free list.
timer->set = set; timer->set = set;
timer->deadline = set->current_time + seconds; timer->deadline = set->current_time_ms + ms;
timer->data = data; timer->data = data;
timer->callback = callback; timer->callback = callback;
@@ -107,11 +107,11 @@ tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t seconds,
return timer; return timer;
} }
void tcp_timerset_step(tcp_timerset_t *set, size_t seconds) void tcp_timerset_step(tcp_timerset_t *set, size_t ms)
{ {
set->current_time += seconds; set->current_time_ms += ms;
if (set->used_list == NULL || set->used_list->deadline > set->current_time) if (set->used_list == NULL || set->used_list->deadline > set->current_time_ms)
// No timeouts triggered // No timeouts triggered
return; return;
@@ -122,7 +122,7 @@ void tcp_timerset_step(tcp_timerset_t *set, size_t seconds)
tcp_timer_t *timeout = set->used_list; tcp_timer_t *timeout = set->used_list;
while (timeout) { while (timeout) {
if (timeout->deadline > set->current_time) if (timeout->deadline > set->current_time_ms)
// This timeout didn't trigger, so the last // This timeout didn't trigger, so the last
// timed out timeout was the previous one. // timed out timeout was the previous one.
break; break;
+3 -3
View File
@@ -17,15 +17,15 @@ struct tcp_timer_t {
}; };
struct tcp_timerset_t { struct tcp_timerset_t {
uint64_t current_time; uint64_t current_time_ms;
tcp_timer_t *used_list; tcp_timer_t *used_list;
tcp_timer_t *free_list; tcp_timer_t *free_list;
tcp_timer_t pool[TCP_MAX_TIMERS]; tcp_timer_t pool[TCP_MAX_TIMERS];
}; };
void tcp_timerset_step(tcp_timerset_t *set, size_t seconds); void tcp_timerset_step(tcp_timerset_t *set, size_t ms);
void tcp_timerset_init(tcp_timerset_t *set); void tcp_timerset_init(tcp_timerset_t *set);
void tcp_timerset_free(tcp_timerset_t *set); void tcp_timerset_free(tcp_timerset_t *set);
void tcp_timer_disable(tcp_timer_t *timer); void tcp_timer_disable(tcp_timer_t *timer);
tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t seconds, tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t ms,
void (*callback)(void*), void *data); void (*callback)(void*), void *data);