summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-26 22:02:16 +0200
committerAnton Kling <anton@kling.gg>2024-06-26 22:02:16 +0200
commit55fef89be9eb9da8b40bfdc1cc20475421ca5554 (patch)
tree99805aeaf4d525808d042dde4f3cb66ebcd96ce0 /kernel
parentfddda835a28bbc52a8d8450395a3e57e181782a8 (diff)
TCP: Delay ACKs to batch together packets ACKed
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/pit.c6
-rw-r--r--kernel/network/tcp.c3
-rw-r--r--kernel/socket.c22
-rw-r--r--kernel/socket.h3
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