diff options
author | Anton Kling <anton@kling.gg> | 2024-06-11 23:52:27 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-06-12 00:12:13 +0200 |
commit | 08d0b7eee74b9f345241faad460d145bb0454736 (patch) | |
tree | 779f1c1db10c4e872a02aac7f4733a97892e310c | |
parent | abf9cf5bec2712465400417cc8232fee2d1cce28 (diff) |
Improve TCP blocking of requests
-rw-r--r-- | kernel/network/tcp.c | 56 | ||||
-rw-r--r-- | kernel/network/tcp.h | 2 | ||||
-rw-r--r-- | kernel/socket.c | 14 | ||||
-rw-r--r-- | kernel/socket.h | 1 |
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; |