summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-11 23:52:27 +0200
committerAnton Kling <anton@kling.gg>2024-06-12 00:12:13 +0200
commit08d0b7eee74b9f345241faad460d145bb0454736 (patch)
tree779f1c1db10c4e872a02aac7f4733a97892e310c
parentabf9cf5bec2712465400417cc8232fee2d1cce28 (diff)
Improve TCP blocking of requests
-rw-r--r--kernel/network/tcp.c56
-rw-r--r--kernel/network/tcp.h2
-rw-r--r--kernel/socket.c14
-rw-r--r--kernel/socket.h1
4 files changed, 43 insertions, 30 deletions
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index fc8d97c..d171722 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -134,25 +134,32 @@ static void tcp_send(struct TcpConnection *con, u8 *buffer, u16 length,
}
void tcp_resend_packets(struct TcpConnection *con) {
- if (con->inflight.num_entries > 0) {
- for (u32 i = 0;; i++) {
- struct TcpPacket *packet;
- int end;
- if (!relist_get(&con->inflight, i, (void *)&packet, &end)) {
- if (end) {
- break;
- }
- continue;
- }
- if (packet->time + 200 > pit_num_ms()) {
- continue;
+ if (0 == con->inflight.num_entries) {
+ return;
+ }
+ int did_resend = 0;
+ for (u32 i = 0;; i++) {
+ struct TcpPacket *packet;
+ int end;
+ if (!relist_get(&con->inflight, i, (void *)&packet, &end)) {
+ if (end) {
+ break;
}
- // resend the packet
- relist_remove(&con->inflight, i);
- tcp_send(con, packet->buffer, packet->length, packet->seq_num,
- packet->payload_length);
- kfree(packet);
+ continue;
+ }
+ if (packet->time + 200 > pit_num_ms()) {
+ continue;
}
+ // resend the packet
+ did_resend = 1;
+ relist_remove(&con->inflight, i);
+ tcp_send(con, packet->buffer, packet->length, packet->seq_num,
+ packet->payload_length);
+ kfree(packet);
+ }
+ if (did_resend) {
+ con->max_inflight = 1;
+ con->window_size = MSS;
}
}
@@ -194,21 +201,17 @@ void tcp_send_syn(struct TcpConnection *con) {
con->seq++;
}
-int tcp_can_send(struct TcpConnection *con, u16 payload_length) {
- if (con->inflight.num_entries > 2) {
+u16 tcp_can_send(struct TcpConnection *con) {
+ if (con->inflight.num_entries > con->max_inflight) {
tcp_resend_packets(con);
return 0;
}
- if (con->seq - con->seq_ack + payload_length > con->current_window_size) {
- tcp_resend_packets(con);
- return 0;
- }
- return 1;
+ return con->current_window_size;
}
int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
u16 payload_length) {
- if (!tcp_can_send(con, payload_length)) {
+ if (0 == tcp_can_send(con)) {
return 0;
}
@@ -326,7 +329,7 @@ void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload,
}
continue;
}
- if (packet->seq_num + packet->payload_length != ack_num) {
+ if (packet->seq_num + packet->payload_length > ack_num) {
continue;
}
relist_remove(&incoming_connection->inflight, i);
@@ -337,6 +340,7 @@ void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload,
}
tcp_resend_packets(incoming_connection);
if (0 == incoming_connection->inflight.num_entries) {
+ incoming_connection->max_inflight++;
u32 rest = incoming_connection->window_size -
incoming_connection->current_window_size;
if (rest > 0) {
diff --git a/kernel/network/tcp.h b/kernel/network/tcp.h
index 836a148..ec253bd 100644
--- a/kernel/network/tcp.h
+++ b/kernel/network/tcp.h
@@ -6,4 +6,4 @@ void handle_tcp(ipv4_t src_ip, ipv4_t dst_ip, const u8 *payload, u32 payload_len
int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
u16 payload_length);
void tcp_close_connection(struct TcpConnection *con);
-int tcp_can_send(struct TcpConnection *con, u16 payload_length);
+u16 tcp_can_send(struct TcpConnection *con);
diff --git a/kernel/socket.c b/kernel/socket.c
index 8b6e12d..79121e7 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -99,6 +99,7 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
ringbuffer_init(&con->incoming_buffer, 8192);
ringbuffer_init(&con->outgoing_buffer, 8192);
relist_init(&con->inflight);
+ con->max_inflight = 1;
stack_push(&listen->incoming_connections, con);
return con;
}
@@ -116,7 +117,8 @@ int tcp_sync_buffer(vfs_fd_t *fd) {
return 0;
}
- if (!tcp_can_send(con, send_buffer_len)) {
+ send_buffer_len = min(tcp_can_send(con), send_buffer_len);
+ if(0 == send_buffer_len) {
return 0;
}
@@ -157,6 +159,11 @@ int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
return -EBADF; // TODO: Check if this is correct.
}
+ len = min(len, tcp_can_send(con));
+ if (0 == len) {
+ return -EWOULDBLOCK;
+ }
+
if (con->no_delay) {
if (!send_tcp_packet(con, buffer, len)) {
return -EWOULDBLOCK;
@@ -187,10 +194,10 @@ int tcp_has_data(vfs_inode_t *inode) {
int tcp_can_write(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
if (con->no_delay) {
- return tcp_can_send(con, 256);
+ return (0 != tcp_can_send(con));
}
return (ringbuffer_unused(&con->outgoing_buffer) > 0) ||
- (tcp_can_send(con, 250));
+ (0 != tcp_can_send(con));
}
int udp_recvfrom(vfs_fd_t *fd, void *buffer, size_t len, int flags,
@@ -317,6 +324,7 @@ int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
ringbuffer_init(&con->outgoing_buffer, 8192);
list_add(&open_tcp_connections, con, NULL);
relist_init(&con->inflight);
+ con->max_inflight = 1;
tcp_send_syn(con);
diff --git a/kernel/socket.h b/kernel/socket.h
index f41e9a1..0cb6865 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -53,6 +53,7 @@ struct TcpConnection {
struct ringbuffer outgoing_buffer;
struct relist inflight;
+ u8 max_inflight;
int no_delay;