summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-07-08 21:37:15 +0200
committerAnton Kling <anton@kling.gg>2024-07-08 21:37:15 +0200
commite49d2a9fa5a485c33a250ce843d44fc6dedea8b5 (patch)
tree4be00773adca0b6c59da6d07602338ff538a7199
parent35292a486c2b44862cac6887441d6fa18148b249 (diff)
Kernel/Net: Don't use kmalloc to create send buffers
Current method is also really bad since it uses multiple copies when it should instead just copy to the send buffer of the network card directly. But I have other things that I want to prioritize first.
-rw-r--r--kernel/drivers/rtl8139.c1
-rw-r--r--kernel/fs/vfs.c10
-rw-r--r--kernel/fs/vfs.h1
-rw-r--r--kernel/init/kernel.c1
-rw-r--r--kernel/kmalloc.c2
-rw-r--r--kernel/network/ethernet.c14
-rw-r--r--kernel/network/ipv4.c5
-rw-r--r--kernel/network/tcp.c17
-rw-r--r--kernel/queue.c9
-rw-r--r--kernel/queue.h1
-rw-r--r--kernel/socket.c69
-rw-r--r--kernel/socket.h1
12 files changed, 91 insertions, 40 deletions
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c
index 98d3f22..669cb6c 100644
--- a/kernel/drivers/rtl8139.c
+++ b/kernel/drivers/rtl8139.c
@@ -68,6 +68,7 @@ void handle_packet(void) {
(!packet_header.data.ROK);
if (error) {
+ klog(LOG_ERROR, "RTL8139 packet error");
current_packet_read = 0;
outb(rtl8139.gen.base_mem_io + 0x37, 0x4);
outb(rtl8139.gen.base_mem_io + 0x37, 0x4 | 0x8);
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 65be4aa..d76e56c 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -41,7 +41,7 @@ vfs_inode_t *vfs_create_inode(
int (*send_signal)(vfs_fd_t *fd, int signal),
int (*connect)(vfs_fd_t *fd, const struct sockaddr *addr,
socklen_t addrlen)) {
- vfs_inode_t *r = kmalloc(sizeof(inode_t));
+ vfs_inode_t *r = kcalloc(1, sizeof(inode_t));
r->inode_num = inode_num;
r->type = type;
r->_has_data = has_data;
@@ -325,14 +325,6 @@ int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset) {
}
int vfs_pread(int fd, void *buf, u64 count, u64 offset) {
- if (fd >= 100) {
- kprintf("EBADF : %x\n", fd);
- return -EBADF;
- }
- if (fd < 0) {
- kprintf("EBADF : %x\n", fd);
- return -EBADF;
- }
vfs_fd_t *vfs_fd = get_vfs_fd(fd, NULL);
if (!vfs_fd) {
return -EBADF;
diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h
index a39982d..640cfbb 100644
--- a/kernel/fs/vfs.h
+++ b/kernel/fs/vfs.h
@@ -48,6 +48,7 @@ struct vfs_inode {
int type;
int (*_has_data)(vfs_inode_t *iinode);
int (*_can_write)(vfs_inode_t *iinode);
+ int (*_is_open)(vfs_inode_t *iinode);
u8 is_open;
int internal_object_type;
void *internal_object;
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 61e863b..2e569cb 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -13,6 +13,7 @@
#include <drivers/rtl8139.h>
#include <drivers/serial.h>
#include <drivers/vbe.h>
+#include <fcntl.h>
#include <fs/devfs.h>
#include <fs/ext2.h>
#include <fs/shm.h>
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index b4a7f54..f5188cc 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -7,7 +7,7 @@
#include <mmu.h>
#include <random.h>
#include <stdint.h>
-#define NEW_ALLOC_SIZE 0x5000
+#define NEW_ALLOC_SIZE 0x40000
// #define KMALLOC_DEBUG
diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c
index 7b1de7f..dbd1b6d 100644
--- a/kernel/network/ethernet.c
+++ b/kernel/network/ethernet.c
@@ -68,14 +68,14 @@ void handle_ethernet(const u8 *packet, u64 packet_length) {
}
}
+u8 ethernet_buffer[0x1000];
void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload,
u64 payload_length) {
- // FIXME: Janky allocation, do this better
u64 buffer_size =
sizeof(struct EthernetHeader) + payload_length + sizeof(u32);
- u8 *buffer = kmalloc(buffer_size);
- memset(buffer, 0, buffer_size);
- u8 *buffer_start = buffer;
+ assert(buffer_size < 0x1000);
+ memset(ethernet_buffer, 0, buffer_size);
+ u8 *buffer = ethernet_buffer;
struct EthernetHeader *eth_header = (struct EthernetHeader *)buffer;
buffer += sizeof(struct EthernetHeader);
memcpy(buffer, payload, payload_length);
@@ -84,8 +84,8 @@ void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload,
memcpy(eth_header->mac_dst, mac_dst, sizeof(u8[6]));
get_mac_address(eth_header->mac_src);
eth_header->type = htons(type);
- *(u32 *)(buffer) = htonl(crc32((const char *)buffer_start, buffer_size - 4));
+ *(u32 *)(buffer) =
+ htonl(crc32((const char *)ethernet_buffer, buffer_size - 4));
- rtl8139_send_data(buffer_start, buffer_size);
- kfree(buffer_start);
+ rtl8139_send_data(ethernet_buffer, buffer_size);
}
diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c
index 69ceef7..6074141 100644
--- a/kernel/network/ipv4.c
+++ b/kernel/network/ipv4.c
@@ -26,6 +26,7 @@ static u16 ip_checksum(const u16 *data, u16 length) {
return htons(~acc);
}
+u8 ipv4_buffer[0x1000];
void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
u16 header[10];
header[0] = (4 /*version*/ << 4) | (5 /*IHL*/);
@@ -46,7 +47,8 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
header[5] = ip_checksum(header, 20);
u16 packet_length = length + 20;
- u8 *packet = kmalloc(packet_length);
+ assert(packet_length < sizeof(ipv4_buffer));
+ u8 *packet = ipv4_buffer;
memcpy(packet, header, 20);
memcpy(packet + 20, payload, length);
@@ -54,7 +56,6 @@ void send_ipv4_packet(ipv4_t ip, u8 protocol, const u8 *payload, u16 length) {
for (; !get_mac_from_ip(ip, mac);)
;
send_ethernet_packet(mac, 0x0800, packet, packet_length);
- kfree(packet);
}
void handle_ipv4(const u8 *payload, u32 packet_length) {
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index 8a56dd1..8717250 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -87,6 +87,7 @@ static void tcp_send(struct TcpConnection *con, u8 *buffer, u16 length,
send_ipv4_packet((ipv4_t){.d = con->outgoing_ip}, 6, buffer, length);
}
+u8 tcp_buffer[0x1000];
void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
struct TcpHeader header;
memset(&header, 0, sizeof(header));
@@ -110,8 +111,10 @@ void tcp_send_empty_payload(struct TcpConnection *con, u8 flags) {
header.checksum = tcp_calculate_checksum(
ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
&header, sizeof(struct TcpHeader) + payload_length);
- int send_len = sizeof(header) + payload_length;
- u8 *send_buffer = kmalloc(send_len);
+ u32 send_len = sizeof(header) + payload_length;
+
+ assert(send_len < sizeof(tcp_buffer));
+ u8 *send_buffer = tcp_buffer;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
@@ -133,13 +136,15 @@ void tcp_close_connection(struct TcpConnection *con) {
if (TCP_STATE_CLOSE_WAIT == con->state) {
tcp_send_empty_payload(con, FIN);
con->state = TCP_STATE_LAST_ACK;
+ tcp_destroy_connection(con); // Client does not appear to respond
+ // with last ack?
return;
}
if (TCP_STATE_ESTABLISHED == con->state) {
// FIXME:
// Book says it should be FIN but observed network traffic says it
// should be FIN|ACK?
- tcp_send_empty_payload(con, FIN | ACK);
+ tcp_send_empty_payload(con, FIN);
con->state = TCP_STATE_FIN_WAIT1;
return;
}
@@ -189,9 +194,9 @@ int send_tcp_packet(struct TcpConnection *con, const u8 *payload,
header.checksum = tcp_calculate_checksum(
ip_address, con->outgoing_ip, (const u8 *)payload, payload_length,
&header, sizeof(struct TcpHeader) + payload_length);
- int send_len = sizeof(header) + payload_length;
- u8 *send_buffer = kmalloc(send_len);
- assert(send_buffer);
+ u32 send_len = sizeof(header) + payload_length;
+ assert(send_len < sizeof(tcp_buffer));
+ u8 *send_buffer = tcp_buffer;
memcpy(send_buffer, &header, sizeof(header));
memcpy(send_buffer + sizeof(header), payload, payload_length);
diff --git a/kernel/queue.c b/kernel/queue.c
index 6d4209d..e1b2943 100644
--- a/kernel/queue.c
+++ b/kernel/queue.c
@@ -43,6 +43,13 @@ int queue_get_entries(struct queue_list *list, struct queue_entry *events,
}
}
}
+ if (QUEUE_WAIT_CLOSE & entry->listen) {
+ if (ptr->inode->_is_open) {
+ if (!ptr->inode->_is_open(ptr->inode)) {
+ should_add = 1;
+ }
+ }
+ }
if (should_add) {
if (events) {
memcpy(events + rc, entry, sizeof(struct queue_entry));
@@ -130,7 +137,7 @@ int queue_mod_entries(int fd, int flag, struct queue_entry *entries,
}
for (int j = 0; j < num_entries; j++) {
if (entry->fd == entries[j].fd) {
- relist_remove(&list->entries, i);
+ assert(relist_remove(&list->entries, i));
kfree(entry);
break;
}
diff --git a/kernel/queue.h b/kernel/queue.h
index 0885f16..4a9cd17 100644
--- a/kernel/queue.h
+++ b/kernel/queue.h
@@ -4,6 +4,7 @@
#define QUEUE_WAIT_READ (1 << 0)
#define QUEUE_WAIT_WRITE (1 << 1)
+#define QUEUE_WAIT_CLOSE (1 << 2)
#define QUEUE_MOD_ADD 0
#define QUEUE_MOD_CHANGE 1
diff --git a/kernel/socket.c b/kernel/socket.c
index fbccac5..cc5a645 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -48,12 +48,30 @@ void tcp_remove_connection(struct TcpConnection *con) {
}
if (c == con) {
relist_remove(&open_tcp_connections, i);
+ ringbuffer_free(&c->incoming_buffer);
+ ringbuffer_free(&c->outgoing_buffer);
kfree(con);
break;
}
}
}
+int num_open_connections(void) {
+ int f = 0;
+ for (int i = 0;; i++) {
+ struct TcpConnection *c;
+ int end;
+ if (!relist_get(&open_tcp_connections, i, (void **)&c, &end)) {
+ if (end) {
+ break;
+ }
+ continue;
+ }
+ f++;
+ }
+ return f;
+}
+
struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
ipv4_t dst_ip, u16 dst_port) {
for (int i = 0;; i++) {
@@ -74,7 +92,11 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
if (c->incoming_port == dst_port) {
struct TcpConnection *new_connection =
kmalloc(sizeof(struct TcpConnection));
- memcpy(new_connection, c, sizeof(struct TcpConnection));
+ new_connection->incoming_port = c->incoming_port;
+ new_connection->incoming_ip = c->incoming_ip;
+
+ new_connection->no_delay = c->no_delay;
+
new_connection->outgoing_port = src_port;
new_connection->outgoing_ip = src_ip.d;
new_connection->state = TCP_STATE_LISTEN;
@@ -94,10 +116,7 @@ struct TcpConnection *tcp_connect_to_listen(ipv4_t src_ip, u16 src_port,
new_connection->snd_wnd = 0;
new_connection->sent_ack = 0;
- new_connection->snd_wnd =
- ringbuffer_unused(&new_connection->outgoing_buffer);
- u32 index;
- assert(relist_add(&open_tcp_connections, new_connection, &index));
+ assert(relist_add(&open_tcp_connections, new_connection, NULL));
assert(relist_add(&c->incoming_connections, new_connection, NULL));
return new_connection;
}
@@ -137,9 +156,24 @@ void tcp_flush_buffers(void) {
}
continue;
}
+ if (TCP_STATE_TIME_WAIT == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
+ if (TCP_STATE_FIN_WAIT2 == c->state) {
+ // TODO: It should actually wait
+ c->state = TCP_STATE_CLOSED;
+ tcp_remove_connection(c);
+ continue;
+ }
if (TCP_STATE_CLOSED == c->state) {
continue;
}
+ if (TCP_STATE_ESTABLISHED != c->state) {
+ continue;
+ }
tcp_sync_buffer(c);
}
}
@@ -233,9 +267,12 @@ void tcp_strip_connection(struct TcpConnection *con) {
void tcp_close(vfs_fd_t *fd) {
struct TcpConnection *con = fd->inode->internal_object;
+ if (TCP_STATE_CLOSED == con->state) {
+ return;
+ }
assert(con);
- tcp_sync_buffer(con);
if (TCP_STATE_ESTABLISHED == con->state) {
+ tcp_sync_buffer(con);
tcp_strip_connection(con);
}
tcp_close_connection(con);
@@ -256,12 +293,16 @@ int tcp_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
int tcp_has_data(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
+ if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
+ }
return !(ringbuffer_isempty(&con->incoming_buffer));
}
int tcp_can_write(vfs_inode_t *inode) {
struct TcpConnection *con = inode->internal_object;
if (TCP_STATE_ESTABLISHED != con->state) {
+ inode->is_open = 0;
return 0;
}
if (con->no_delay) {
@@ -271,6 +312,11 @@ int tcp_can_write(vfs_inode_t *inode) {
(0 != tcp_can_send(con));
}
+int tcp_is_open(vfs_inode_t *inode) {
+ struct TcpConnection *con = inode->internal_object;
+ return (TCP_STATE_ESTABLISHED == con->state);
+}
+
int tcp_write(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
(void)offset;
struct TcpConnection *con = fd->inode->internal_object;
@@ -462,6 +508,7 @@ int tcp_connect(vfs_fd_t *fd, const struct sockaddr *addr, socklen_t addrlen) {
fd->inode->_has_data = tcp_has_data;
fd->inode->_can_write = tcp_can_write;
+ fd->inode->_is_open = tcp_is_open;
fd->inode->write = tcp_write;
fd->inode->read = tcp_read;
fd->inode->close = tcp_close;
@@ -535,12 +582,6 @@ int uds_open(const char *path) {
return fd[0];
}
-int tcp_listen_has_data(vfs_inode_t *inode) {
- const SOCKET *s = (SOCKET *)inode->internal_object;
- const struct TcpListen *tcp_listen = s->object;
- return !stack_isempty(&tcp_listen->incoming_connections);
-}
-
int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
(void)address;
(void)address_len;
@@ -587,6 +628,7 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
NULL /*create_file*/, tcp_read, tcp_write, tcp_close /*close*/,
NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/,
NULL /*stat*/, NULL /*send_signal*/, NULL /*connect*/);
+ inode->_is_open = tcp_is_open;
assert(inode);
return vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, NULL);
}
@@ -618,7 +660,7 @@ struct TcpConnection *tcp_get_incoming_connection(struct TcpConnection *con,
if (!c) {
continue;
}
- if (TCP_STATE_ESTABLISHED == c->state) {
+ if (TCP_STATE_LISTEN != c->state) {
if (remove) {
assert(relist_remove(&con->incoming_connections, i));
}
@@ -739,6 +781,7 @@ int tcp_create_fd(int is_nonblock) {
kfree(con);
return -ENOMEM;
}
+ inode->_is_open = tcp_is_open;
int fd = vfs_create_fd(O_RDWR | (is_nonblock ? O_NONBLOCK : 0), 0,
0 /*is_tty*/, inode, NULL);
if (fd < 0) {
diff --git a/kernel/socket.h b/kernel/socket.h
index 35074a1..efe0104 100644
--- a/kernel/socket.h
+++ b/kernel/socket.h
@@ -40,7 +40,6 @@ struct UdpConnection {
};
struct TcpConnection {
-
int state;
u16 incoming_port;