diff options
author | Anton Kling <anton@kling.gg> | 2024-06-26 22:02:16 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-06-26 22:02:16 +0200 |
commit | 55fef89be9eb9da8b40bfdc1cc20475421ca5554 (patch) | |
tree | 99805aeaf4d525808d042dde4f3cb66ebcd96ce0 /kernel | |
parent | fddda835a28bbc52a8d8450395a3e57e181782a8 (diff) |
TCP: Delay ACKs to batch together packets ACKed
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/drivers/pit.c | 6 | ||||
-rw-r--r-- | kernel/network/tcp.c | 3 | ||||
-rw-r--r-- | kernel/socket.c | 22 | ||||
-rw-r--r-- | kernel/socket.h | 3 |
4 files changed, 33 insertions, 1 deletions
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c index 80f55aa..db9cd2a 100644 --- a/kernel/drivers/pit.c +++ b/kernel/drivers/pit.c @@ -43,10 +43,16 @@ void set_pit_count(u16 _hertz) { outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8); } +int last_flush = 0; + extern int is_switching_tasks; void int_clock(reg_t *regs) { clock_num_ms_ticks += 5; switch_counter++; + if (clock_num_ms_ticks - last_flush > 50) { + tcp_flush_acks(); + last_flush = clock_num_ms_ticks; + } if (switch_counter >= hertz) { EOI(0x20); switch_counter = 0; diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c index bb48f53..e6febba 100644 --- a/kernel/network/tcp.c +++ b/kernel/network/tcp.c @@ -84,6 +84,7 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) { header.dst_port = htons(con->outgoing_port); header.seq_num = htonl(con->snd_nxt); if (flags & ACK) { + con->should_send_ack = 0; header.ack_num = htonl(con->rcv_nxt); } else { header.ack_num = 0; @@ -282,7 +283,7 @@ void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload, int rc = ringbuffer_write(&con->incoming_buffer, tcp_payload, tcp_payload_length); con->rcv_nxt += rc; - tcp_send_empty_payload(con, ACK); + con->should_send_ack = 1; } break; } diff --git a/kernel/socket.c b/kernel/socket.c index bd7f755..54f7598 100644 --- a/kernel/socket.c +++ b/kernel/socket.c @@ -72,6 +72,27 @@ struct TcpConnection *tcp_find_connection(ipv4_t src_ip, u16 src_port, return NULL; } +void tcp_flush_acks(void) { + for (int i = 0;; i++) { + struct TcpConnection *c; + int end; + if (!relist_get(&open_tcp_connections, i, (void **)&c, &end)) { + if (end) { + break; + } + continue; + } + if (TCP_STATE_CLOSED == c->state) { + continue; + } + if (!c->should_send_ack) { + continue; + } + c->should_send_ack = 0; + tcp_send_empty_payload(c, ACK); + } +} + u16 tcp_find_free_port(u16 suggestion) { for (int i = 0;; i++) { struct TcpConnection *c; @@ -580,6 +601,7 @@ int tcp_create_fd(int is_nonblock) { return -ENOMEM; } con->state = TCP_STATE_CLOSED; + con->should_send_ack = 0; vfs_inode_t *inode = vfs_create_inode( 0 /*inode_num*/, FS_TYPE_UNIX_SOCKET, NULL, always_can_write, 1, con, diff --git a/kernel/socket.h b/kernel/socket.h index 454992c..e881111 100644 --- a/kernel/socket.h +++ b/kernel/socket.h @@ -64,6 +64,8 @@ struct TcpConnection { u32 rcv_nxt; u32 rcv_adv; + int should_send_ack; + u32 snd_una; u32 snd_nxt; u32 snd_max; @@ -142,4 +144,5 @@ u16 tcp_get_free_port(void); int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len); void tcp_remove_connection(struct TcpConnection *con); +void tcp_flush_acks(void); #endif |