added rtt and rtt deviation calculation for the tcp layer
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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 */
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
memmove(connection->out_buffer, connection->out_buffer + newly_acked_bytes, connection->snd_wnd - newly_acked_bytes);
|
|
||||||
connection->snd_wnd -= newly_acked_bytes;
|
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);
|
||||||
|
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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user