general cleanups

This commit is contained in:
cozis
2023-10-29 22:38:14 +01:00
parent 5f3f7dc66d
commit 733597b6aa
16 changed files with 1525 additions and 917 deletions
+3
View File
@@ -4,3 +4,6 @@
[submodule "3p/tinycthread"]
path = 3p/tinycthread
url = https://github.com/tinycthread/tinycthread.git
[submodule "3p/packetdrill"]
path = 3p/packetdrill
url = https://github.com/google/packetdrill.git
+1
Submodule 3p/packetdrill added at 8595c94c9c
+5 -46
View File
@@ -3,58 +3,17 @@
int main(void)
{
microtcp_errcode_t errcode;
microtcp_t *mtcp = microtcp_create("10.0.0.5", "10.0.0.4", NULL, NULL);
if (mtcp == NULL) {
fprintf(stderr, "Error: Failed to instanciate microtcp stack\n");
return -1;
}
uint16_t port = 8081;
microtcp_socket_t *server = microtcp_open(mtcp, port, &errcode);
if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
microtcp_destroy(mtcp);
return -1;
}
assert(server);
fprintf(stderr, "Listening on port %d\n", port);
microtcp_socket_t *server = microtcp_open(mtcp, port, NULL);
while (1) {
fprintf(stderr, "About to accept\n");
microtcp_socket_t *client = microtcp_accept(server, false, &errcode);
if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
break;
}
fprintf(stderr, "Accepted a connection\n");
microtcp_socket_t *client = microtcp_accept(server, false, NULL);
char buffer[1024];
size_t num = microtcp_recv(client, buffer, sizeof(buffer), false, &errcode);
if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled;
}
fprintf(stderr, "(%d bytes received)\n", (int) num);
size_t sent1 = microtcp_send(client, "echo: ", 6, false, &errcode);
if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled;
}
fprintf(stderr, "(%d bytes sent 1)\n", (int) sent1);
size_t sent2 = microtcp_send(client, buffer, num, false, &errcode);
if (errcode) {
fprintf(stderr, "Error: %s\n", microtcp_strerror(errcode));
goto handled;
}
fprintf(stderr, "(%d bytes sent 2)\n", (int) sent2);
handled:
size_t num = microtcp_recv(client, buffer, sizeof(buffer), false, NULL);
microtcp_send(client, "echo: ", 6, false, NULL);
microtcp_send(client, buffer, num, false, NULL);
microtcp_close(client);
}
+25
View File
@@ -0,0 +1,25 @@
int main(void)
{
microtcp_t *mtcp = microtcp_create(..);
uint16_t port = 8080;
microtcp_socket_t *socket = microtcp_open(mtcp, port, 0);
microtcp_mux_t *mux = microtcp_mux_create(mtcp);
for (int i = 0; i < 3; i++) {
microtcp_socket_t *accepted = microtcp_accept(socket, 0, 0);
microtcp_mux_register(mux, accepted, MICROTCP_MUX_RECV | MICROTCP_MUX_SEND);
}
for (microtcp_muxevent_t event; microtcp_mux_wait(mux, &event)) {
if (event.events & MICROTCP_MUX_RECV) {
// Il socket "event.socket" ha dei dati da leggere
} else {
// Il socket "event.socket" ha spazio per inviare
}
}
microtcp_destroy(mtcp);
}
+4 -7
View File
@@ -48,13 +48,13 @@ MEMDBG=valgrind
LIBDIR = 3p/lib
INCDIR = 3p/include
CFLAGS = $(CFLAGS_PLATFORM) -I$(INCDIR) -Ibuild/ -Wall -Wextra
LFLAGS = -ltuntap $(LFLAGS_PLATFORM) -L$(LIBDIR)
CFLAGS = $(CUSTOM_CFLAGS) $(CFLAGS_PLATFORM) -I$(INCDIR) -Ibuild/ -Wall -Wextra
LFLAGS = $(CUSTOM_LFLAGS) -ltuntap $(LFLAGS_PLATFORM) -L$(LIBDIR)
ifeq ($(MEMDBG),drmemory)
CFLAGS += -gdwarf-2
else
CFLAGS += -g
CFLAGS += -g3
endif
.PHONY: all clean
@@ -154,7 +154,4 @@ report: build/test
gcov -b build/test-tcp_timer.c
clean:
rm build/*.gcda build/*.gcno
rm -fr build
rm -fr 3p/libtuntap/build
rm -f 3p/lib/* 3p/include/*
rm -fr build 3p/libtuntap/build 3p/lib/* 3p/include/*
+1 -11
View File
@@ -690,17 +690,7 @@ arp_process_result_t arp_process_packet(arp_state_t *state, const void *packet,
ARP_DEBUG_LOG("Invalid hardware or protocol address size %d or %d (expected %d and %d)", packet2->hardware_len, packet2->protocol_len, 6, 4);
return ARP_PROCESS_RESULT_INVALID;
}
/*
ARP_DEBUG_LOG("ARP from %d.%d.%d.%d to %d.%d.%d.%d",
((uint8_t*) &packet2->sender_protocol_address)[0],
((uint8_t*) &packet2->sender_protocol_address)[1],
((uint8_t*) &packet2->sender_protocol_address)[2],
((uint8_t*) &packet2->sender_protocol_address)[3],
((uint8_t*) &packet2->target_protocol_address)[0],
((uint8_t*) &packet2->target_protocol_address)[1],
((uint8_t*) &packet2->target_protocol_address)[2],
((uint8_t*) &packet2->target_protocol_address)[3]);
*/
bool merge = arp_translation_table_update(&state->table, packet2->sender_hardware_address,
packet2->sender_protocol_address, state->cache_timeout);
+6
View File
@@ -26,4 +26,10 @@ typedef struct {
#define COUNT(X) ((int) (sizeof(X) / sizeof((X)[0])))
#define SLICE(X) ((slice_t) {.ptr=&(X), .len=sizeof(X)})
#define UNPACK_IP(IP) \
((IP) >> 0 & 0xff), \
((IP) >> 8 & 0xff), \
((IP) >> 16 & 0xff), \
((IP) >> 24 & 0xff)
#endif /* MICROTCP_DEFS_H */
+3 -1
View File
@@ -89,7 +89,9 @@ void icmp_process_packet(icmp_state_t *state, ip_address_t ip, const void *src,
}
if (state->output_ptr == NULL || state->output_len < len) {
ICMP_DEBUG_LOG("Ignoring ECHO REQUEST because the output buffer is too small for an ECHO REPLY (have %d, need %d)", (int) state->output_len, (int) len);
ICMP_DEBUG_LOG("Ignoring ECHO REQUEST because the output buffer "
"is too small for an ECHO REPLY (have %d, need %d)",
(int) state->output_len, (int) len);
return;
}
+1 -1
View File
@@ -22,7 +22,7 @@ typedef struct {
uint32_t src_ip;
uint32_t dst_ip;
char payload[];
} ip_packet_t;
} __attribute__((packed)) ip_packet_t;
static_assert(sizeof(ip_packet_t) == 20);
typedef enum {
+50 -27
View File
@@ -70,7 +70,7 @@ struct buffer_t {
buffer_t *prev;
buffer_t *next;
size_t used;
char data[1518];
char data[1218];
};
typedef enum {
@@ -143,6 +143,7 @@ const char *microtcp_strerror(microtcp_errcode_t errcode)
case MICROTCP_ERRCODE_CANTBLOCK: return "Can't execute a blocking call for this function";
case MICROTCP_ERRCODE_WOULDBLOCK: return "Can't executa e non-blocking call for this function";
case MICROTCP_ERRCODE_NOTCONNECTION: return "Invalid operation on a non-connection socket";
case MICROTCP_ERRCODE_PEERCLOSED: return "Peer closed the connection";
}
return "???";
}
@@ -374,6 +375,7 @@ process_packet(microtcp_t *mtcp, const void *packet, size_t len)
const ethernet_frame_t *frame = packet;
switch (net_to_cpu_u16(frame->proto)) {
case ETHERNET_PROTOCOL_ARP:
arp_process_packet(&mtcp->arp_state, frame+1, len - sizeof(ethernet_frame_t));
break;
@@ -644,6 +646,7 @@ static microtcp_socket_t*
pop_socket_struct_from_free_list(microtcp_t *mtcp)
{
microtcp_socket_t *socket = mtcp->free_socket_list;
if (socket)
mtcp->free_socket_list = socket->next;
return socket;
}
@@ -689,18 +692,24 @@ static void
signal_events_to_muxes_associated_to_socket(microtcp_socket_t *socket, int events);
#endif
static void ready_to_accept(void *data)
static void listener_event_callback(void *data, tcp_listenevent_t event)
{
microtcp_socket_t *socket = data;
(void) socket;
#ifdef MICROTCP_BACKGROUND_THREAD
cnd_signal(&socket->something_to_accept);
switch (event) {
case TCP_LISTENEVENT_ACCEPT: cnd_signal(&socket->something_to_accept); break;
}
#endif
#ifdef MICROTCP_USING_MUX
MICROTCP_DEBUG_LOG("Signaling ACCEPT to muxes");
signal_events_to_muxes_associated_to_socket(socket, MICROTCP_MUX_ACCEPT);
int flags = 0;
switch (event) {
case TCP_LISTENEVENT_ACCEPT: flags = MICROTCP_MUX_ACCEPT; MICROTCP_DEBUG_LOG("Signaling ACCEPT to muxes"); break;
}
if (flags)
signal_events_to_muxes_associated_to_socket(socket, flags);
#endif
}
@@ -717,7 +726,7 @@ microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port,
goto unlock_and_exit; // Socket limit reached
}
tcp_listener_t *listener = tcp_listener_create(&mtcp->tcp_state, port, false, socket, ready_to_accept);
tcp_listener_t *listener = tcp_listener_create(&mtcp->tcp_state, port, false, socket, listener_event_callback);
if (listener == NULL) {
// FIXME: This error code should be more specific,
// but the TCP module isn't stable yet
@@ -786,6 +795,8 @@ void microtcp_close(microtcp_socket_t *socket)
break;
case SOCKET_CONNECTION:
if (socket->connection) // Only need to close the connection
// if the peer didn't already.
tcp_connection_destroy(socket->connection);
break;
}
@@ -796,33 +807,34 @@ void microtcp_close(microtcp_socket_t *socket)
UNLOCK_WHEN_THREADED(mtcp);
}
static void ready_to_recv(void *data)
static void conn_event_callback(void *data, tcp_connevent_t event)
{
microtcp_socket_t *socket = data;
(void) socket;
#ifdef MICROTCP_BACKGROUND_THREAD
cnd_signal(&socket->something_to_recv);
switch (event) {
case TCP_CONNEVENT_RECV: MICROTCP_DEBUG_LOG("Signal RECV"); cnd_signal(&socket->something_to_recv); break;
case TCP_CONNEVENT_SEND: MICROTCP_DEBUG_LOG("Signal SEND"); cnd_signal(&socket->something_to_send); break;
case TCP_CONNEVENT_RESET:
case TCP_CONNEVENT_CLOSE:
socket->connection = NULL;
break;
}
#endif
#ifdef MICROTCP_USING_MUX
MICROTCP_DEBUG_LOG("Signaling RECV to muxes");
signal_events_to_muxes_associated_to_socket(socket, MICROTCP_MUX_RECV);
#endif
}
static void ready_to_send(void *data)
{
microtcp_socket_t *socket = data;
(void) socket;
#ifdef MICROTCP_BACKGROUND_THREAD
cnd_signal(&socket->something_to_send);
#endif
#ifdef MICROTCP_USING_MUX
MICROTCP_DEBUG_LOG("Signaling SEND to muxes");
signal_events_to_muxes_associated_to_socket(socket, MICROTCP_MUX_SEND);
// TODO: Maybe signal closing and reset events to muxes?
int flags;
switch (event) {
case TCP_CONNEVENT_RECV: flags = MICROTCP_MUX_RECV; MICROTCP_DEBUG_LOG("Signaling RECV to muxes"); break;
case TCP_CONNEVENT_SEND: flags = MICROTCP_MUX_SEND; MICROTCP_DEBUG_LOG("Signaling SEND to muxes"); break;
default: flags = 0; break;
}
if (flags)
signal_events_to_muxes_associated_to_socket(socket, flags);
#endif
}
@@ -847,7 +859,7 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket,
goto unlock_and_exit; // Socket limit reached
}
tcp_connection_t *connection = tcp_listener_accept(socket->listener, socket2, ready_to_recv, ready_to_send);
tcp_connection_t *connection = tcp_listener_accept(socket->listener, socket2, conn_event_callback);
#ifdef MICROTCP_BACKGROUND_THREAD
while (!connection && !no_block) {
@@ -856,7 +868,7 @@ microtcp_socket_t *microtcp_accept(microtcp_socket_t *socket,
push_unlinked_socket_into_free_list(mtcp, socket2);
goto unlock_and_exit;
}
connection = tcp_listener_accept(socket->listener, socket2, ready_to_recv, ready_to_send);
connection = tcp_listener_accept(socket->listener, socket2, conn_event_callback);
}
#else
if (!connection) {
@@ -916,6 +928,12 @@ size_t microtcp_recv(microtcp_socket_t *socket,
return 0;
}
if (socket->connection == NULL) {
if (errcode)
*errcode = MICROTCP_ERRCODE_PEERCLOSED;
return 0;
}
size_t num;
microtcp_t *mtcp = socket->mtcp;
microtcp_errcode_t errcode2 = MICROTCP_ERRCODE_NONE;
@@ -962,6 +980,11 @@ size_t microtcp_send(microtcp_socket_t *socket,
return 0;
}
if (socket->connection == NULL) {
if (errcode)
*errcode = MICROTCP_ERRCODE_PEERCLOSED;
return 0;
}
size_t num;
microtcp_t *mtcp = socket->mtcp;
+3
View File
@@ -32,6 +32,9 @@ typedef enum {
// Returned by microtcp_accept, microtcp_recv and microtcp_send
MICROTCP_ERRCODE_WOULDBLOCK,
// Returned by microtcp_recv, microtcp_send
MICROTCP_ERRCODE_PEERCLOSED,
} microtcp_errcode_t;
typedef struct {
+1287 -731
View File
File diff suppressed because it is too large Load Diff
+73 -26
View File
@@ -12,8 +12,8 @@
#define TCP_MAX_TIMEOUTS 1024
#define TCP_MAX_LISTENERS 32
#define TCP_MAX_SOCKETS 1024
#define TCP_INPUT_BUFFER_SIZE 1024
#define TCP_OUTPUT_BUFFER_SIZE 1024
#define TCP_IBUFFER_SIZE 1024
#define TCP_OBUFFER_SIZE 1024
typedef struct tcp_state_t tcp_state_t; // Predeclare for cyclic references
@@ -36,12 +36,29 @@ typedef struct {
uint16_t checksum;
uint16_t urgent_pointer;
char payload[];
} tcp_segment_t;
} __attribute__((packed)) tcp_segment_t;
static_assert(sizeof(tcp_segment_t) == 20);
typedef struct tcp_connection_t tcp_connection_t;
typedef struct tcp_listener_t tcp_listener_t;
// After receiving a reset or close event, no
// methods shall be called on the connection
// object, not even to close it.
typedef enum {
TCP_CONNEVENT_CLOSE,
TCP_CONNEVENT_RESET,
TCP_CONNEVENT_RECV,
TCP_CONNEVENT_SEND,
} tcp_connevent_t;
typedef enum {
TCP_LISTENEVENT_ACCEPT,
} tcp_listenevent_t;
typedef void (*tcp_conneventcb_t)(void *data, tcp_connevent_t);
typedef void (*tcp_listeneventcb_t)(void *data, tcp_listenevent_t);
struct tcp_listener_t {
tcp_state_t *state;
tcp_listener_t *prev;
@@ -53,20 +70,35 @@ struct tcp_listener_t {
// its still holding.
// In this state the listener can be reopened by setting the "closed"
// flag to true (and keeping the old connections intact).
// Port the listener is listening onto
uint16_t port;
tcp_connection_t *accepted_list;
tcp_connection_t *non_established_list;
tcp_connection_t *non_accepted_queue_head;
tcp_connection_t *non_accepted_queue_tail;
void (*callback_ready_to_accept)(void*);
void *callback_data;
// Number of connection
int count;
// List of established and accepted connections
tcp_connection_t *accepted;
// List of connections which aren't in an established
// state yet.
tcp_connection_t *noestab;
// Queue of connections ready to be accepted
// (established but not accepted)
tcp_connection_t *qhead;
tcp_connection_t *qtail;
tcp_listeneventcb_t cb_event;
void *cb_data;
};
typedef enum {
TCP_STATE_CLOSED = 0,
TCP_STATE_LISTEN,
TCP_STATE_SYN_SENT,
TCP_STATE_SYN_RCVD,
TCP_STATE_ESTAB,
TCP_STATE_ESTABLISHED,
TCP_STATE_FIN_WAIT_1,
TCP_STATE_FIN_WAIT_2,
TCP_STATE_CLOSE_WAIT,
@@ -76,27 +108,29 @@ typedef enum {
} tcp_connstate_t;
struct tcp_connection_t {
tcp_listener_t *listener; // Listener that accepted this connection
tcp_connection_t *next;
tcp_connection_t *prev;
void *callback_data;
void (*callback_ready_to_recv)(void*);
void (*callback_ready_to_send)(void*);
tcp_conneventcb_t cb_event;
void *cb_data;
tcp_connstate_t state;
ip_address_t peer_ip; // Network byte order
uint16_t peer_port; // CPU byte order
uint64_t estimated_rtt;
uint64_t estimated_dev;
bool calculating_rtt;
uint32_t rtt_calc_seq;
uint64_t rtt_calc_time;
// From RFC 6298, Section 2
// To compute the current RTO, a TCP sender maintains two state
// variables, SRTT (smoothed round-trip time) and RTTVAR (round-trip
// time variation). In addition, we assume a clock granularity of G
// seconds.
float srtt;
float rttvar;
tcp_timer_t *retr_timer;
tcp_timer_t *wait_timer;
// Send Sequence Space
//
@@ -149,10 +183,24 @@ struct tcp_connection_t {
// It's the sequence number of the last
// byte sent and acknowledged by the peer.
bool in_buffer_syn;
bool in_buffer_fin;
char in_buffer[TCP_INPUT_BUFFER_SIZE];
char out_buffer[TCP_OUTPUT_BUFFER_SIZE];
uint32_t snd_wl1; // SND.WL1 from RFC 9293
// segment sequence number used for last
// window update.
uint32_t snd_wl2; // SND.WL2 from RFC 9293
// segment acknowledgment number used for
// last window update.
uint32_t last_acked; // Last sequence number of the peer that was ACKed
// If true, the next segment which will empty the
// output buffer will contain a FIN.
bool send_fin_when_fully_flushed;
bool waiting_ack_for_syn;
bool waiting_ack_for_fin;
size_t oused;
char idata[TCP_IBUFFER_SIZE];
char odata[TCP_OBUFFER_SIZE];
};
typedef struct {
@@ -180,10 +228,9 @@ void tcp_init(tcp_state_t *tcp_state, ip_address_t ip, tcp_callback
void tcp_free(tcp_state_t *tcp_state);
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);
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 *cb_data, tcp_listeneventcb_t func);
void tcp_listener_destroy(tcp_listener_t *listener);
tcp_connection_t *tcp_listener_accept(tcp_listener_t *listener, void *callback_data, void (*callback_ready_to_recv)(void*), void (*callback_ready_to_send)(void*));
tcp_connection_t *tcp_listener_accept(tcp_listener_t *listener, void *cb_data, tcp_conneventcb_t func);
void tcp_connection_destroy(tcp_connection_t *connection);
void tcp_connection_finish(tcp_connection_t *connection);
size_t tcp_connection_recv(tcp_connection_t *connection, void *dst, size_t len);
size_t tcp_connection_send(tcp_connection_t *connection, const void *src, size_t len);
+4 -2
View File
@@ -61,6 +61,8 @@ tcp_timer_t *tcp_timer_create(tcp_timerset_t *set, size_t ms,
// first item of the free list.
timer->set = set;
timer->set_time = set->current_time_ms;
timer->trg_time = ms;
timer->deadline = set->current_time_ms + ms;
timer->data = data;
timer->callback = callback;
@@ -125,7 +127,7 @@ void tcp_timerset_step(tcp_timerset_t *set, size_t ms)
// Scan through all of the timeouts that just triggered
tcp_timer_t *timeout = set->used_list;
while (timeout) {
do {
if (timeout->deadline > set->current_time_ms)
// This timeout didn't trigger, so the last
@@ -137,7 +139,7 @@ void tcp_timerset_step(tcp_timerset_t *set, size_t ms)
timedout_tail = timeout;
timeout = timeout->next;
}
} while (timeout);
// Now put the list of timed out timeouts back
// into the free list
+2
View File
@@ -14,6 +14,8 @@ struct tcp_timer_t {
tcp_timerset_t *set;
tcp_timer_t *prev;
tcp_timer_t *next;
uint64_t set_time;
uint64_t trg_time;
uint64_t deadline;
void (*callback)(void *data);
void *data;
+9 -17
View File
@@ -17,15 +17,14 @@ static bool is_hex_digit(char c)
static int int_from_hex_digit(char c)
{
assert(is_hex_digit(c));
if (c >= 'A' || c <= 'F')
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
if (c >= 'a' || c <= 'f')
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return c - '0';
}
bool parse_mac(const char *src, size_t len,
mac_address_t *mac)
bool parse_mac(const char *src, size_t len, mac_address_t *mac)
{
if (src == NULL || len != 17
|| !is_hex_digit(src[0])
@@ -49,20 +48,13 @@ bool parse_mac(const char *src, size_t len,
static const char max_char_map[] = "0123456789ABCDEF";
if (mac) {
mac->data[0] = max_char_map[int_from_hex_digit(src[ 0])] << 4
| max_char_map[int_from_hex_digit(src[ 1])];
mac->data[1] = max_char_map[int_from_hex_digit(src[ 3])] << 4
| max_char_map[int_from_hex_digit(src[ 4])];
mac->data[2] = max_char_map[int_from_hex_digit(src[ 6])] << 4
| max_char_map[int_from_hex_digit(src[ 7])];
mac->data[3] = max_char_map[int_from_hex_digit(src[ 9])] << 4
| max_char_map[int_from_hex_digit(src[10])];
mac->data[4] = max_char_map[int_from_hex_digit(src[12])] << 4
| max_char_map[int_from_hex_digit(src[13])];
mac->data[5] = max_char_map[int_from_hex_digit(src[15])] << 4
| max_char_map[int_from_hex_digit(src[16])];
if (mac)
for (int i = 0; i < 6; i++) {
int u = int_from_hex_digit(src[i * 3 + 0]);
int v = int_from_hex_digit(src[i * 3 + 1]);
mac->data[i] = (max_char_map[u] << 4) | max_char_map[v];
}
return true;
}