Split packet queues

This commit is contained in:
Mark
2020-03-20 22:12:51 +02:00
parent 7002562146
commit 8954fa8fef
7 changed files with 144 additions and 28 deletions
+1
View File
@@ -102,6 +102,7 @@ OBJS+=$(O)/sys/sys_net.o \
$(O)/net/inet.o \
$(O)/net/icmp.o \
$(O)/net/udp.o \
$(O)/net/raw.o \
$(O)/net/if.o \
$(O)/net/util.o
DIRS+=$(O)/net
+13 -1
View File
@@ -6,11 +6,23 @@ struct netdev;
#define PACKET_DATA_MAX (4056)
struct packet {
size_t size;
struct packet *prev, *next;
struct netdev *dev;
size_t refcount;
char data[PACKET_DATA_MAX];
};
struct packet_qh {
struct packet *packet;
struct packet_qh *prev, *next;
};
struct packet_queue {
struct packet_qh *head, *tail;
};
void packet_ref(struct packet *p);
void packet_unref(struct packet *p);
void packet_queue_init(struct packet_queue *q);
void packet_queue_push(struct packet_queue *q, struct packet *p);
struct packet *packet_queue_pop(struct packet_queue *q);
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "sys/types.h"
struct vfs_ioctx;
struct ofile;
struct sockaddr;
struct packet;
int raw_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto);
ssize_t raw_socket_send(struct vfs_ioctx *ioctx, struct ofile *fd, const void *buf, size_t lim, struct sockaddr *sa, size_t salen);
ssize_t raw_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, size_t lim, struct sockaddr *sa, size_t *salen);
int raw_socket_bind(struct vfs_ioctx *ioctx, struct ofile *fd, struct sockaddr *sa, size_t len);
int raw_setsockopt(struct vfs_ioctx *ioctx, struct ofile *fd, int optname, void *optval, size_t optlen);
void raw_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd);
void raw_packet_handle(struct packet *p);
+4
View File
@@ -5,9 +5,13 @@
#define PF_INET 2
#define AF_INET PF_INET
#define PF_PACKET 17
#define AF_PACKET PF_PACKET
/* Socket types */
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
#define SOCK_RAW 3
/* sockopts */
#define SO_BINDTODEVICE 25
+61 -20
View File
@@ -9,17 +9,19 @@
#include "sys/panic.h"
#include "sys/debug.h"
#include "fs/ofile.h"
#include "sys/heap.h"
#include "sys/spin.h"
#include "net/packet.h"
#include "net/eth.h"
#include "net/udp.h"
#include "net/raw.h"
#include "net/net.h"
#include "net/if.h"
static struct thread netd_thread = {0};
static spin_t g_rxq_lock = 0;
static struct packet *g_rxq_head, *g_rxq_tail;
static struct packet_queue g_rxq;
static struct packet *packet_create(void);
static void packet_free(struct packet *p);
@@ -27,6 +29,8 @@ static void packet_free(struct packet *p);
static inline void net_handle_packet(struct packet *p) {
// TODO: check if interface sends packet not in ethernet format
eth_handle_frame(p);
// Notify all raw sockets
raw_packet_handle(p);
}
static void net_daemon(void) {
@@ -34,7 +38,7 @@ static void net_daemon(void) {
uintptr_t irq;
while (1) {
if (!g_rxq_head) {
if (!g_rxq.head) {
// qword writes are atomic (when storing new head)
// so I guess checking if ANYTHING is present
// before locking is a good idea to avoid unnecessary
@@ -45,14 +49,8 @@ static void net_daemon(void) {
}
spin_lock_irqsave(&g_rxq_lock, &irq);
_assert(g_rxq_head);
p = g_rxq_head;
g_rxq_head = g_rxq_head->next;
if (!g_rxq_head) {
g_rxq_tail = NULL;
} else {
g_rxq_head->prev = NULL;
}
p = packet_queue_pop(&g_rxq);
_assert(p);
spin_release_irqrestore(&g_rxq_lock, &irq);
net_handle_packet(p);
@@ -61,6 +59,43 @@ static void net_daemon(void) {
}
}
static inline struct packet_qh *packet_qh_create(struct packet *p) {
struct packet_qh *qh = kmalloc(sizeof(struct packet_qh));
_assert(qh);
qh->packet = p;
return qh;
}
void packet_queue_push(struct packet_queue *pq, struct packet *p) {
struct packet_qh *qh = packet_qh_create(p);
if (pq->tail) {
pq->tail->next = qh;
} else {
pq->head = qh;
}
qh->prev = pq->tail;
qh->next = NULL;
pq->tail = qh;
}
struct packet *packet_queue_pop(struct packet_queue *pq) {
struct packet_qh *qh = pq->head;
_assert(qh);
pq->head = qh->next;
if (!pq->head) {
pq->tail = NULL;
}
struct packet *p = qh->packet;
kfree(qh);
return p;
}
void packet_queue_init(struct packet_queue *pq) {
pq->head = NULL;
pq->tail = NULL;
}
static struct packet *packet_create(void) {
struct packet *packet;
uintptr_t page = amd64_phys_alloc_page();
@@ -101,20 +136,15 @@ int net_receive(struct netdev *dev, const void *data, size_t len) {
packet_ref(p);
spin_lock(&g_rxq_lock);
p->next = NULL;
p->prev = g_rxq_tail;
if (g_rxq_tail) {
g_rxq_tail->next = p;
} else {
g_rxq_head = p;
}
g_rxq_tail = p;
packet_queue_push(&g_rxq, p);
spin_release(&g_rxq_lock);
return 0;
}
void net_daemon_start(void) {
packet_queue_init(&g_rxq);
_assert(thread_init(&netd_thread, (uintptr_t) net_daemon, NULL, 0) == 0);
netd_thread.pid = thread_alloc_pid(0);
sched_queue(&netd_thread);
@@ -124,15 +154,26 @@ int net_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type
_assert(fd);
fd->flags = OF_SOCKET;
if (dom == AF_INET) {
switch (dom) {
case AF_INET:
switch (type) {
case SOCK_DGRAM:
return udp_socket_open(ioctx, fd, dom, type, proto);
default:
break;
}
break;
case AF_PACKET:
switch (type) {
case SOCK_RAW:
return raw_socket_open(ioctx, fd, dom, type, proto);
default:
break;
}
break;
default:
break;
}
return -EINVAL;
}
+43
View File
@@ -0,0 +1,43 @@
#include "user/socket.h"
#include "sys/assert.h"
#include "net/packet.h"
#include "fs/ofile.h"
#include "sys/heap.h"
#include "net/raw.h"
struct raw_socket {
struct packet_queue queue;
struct raw_socket *prev, *next;
};
static struct raw_socket *g_raw_sockets = NULL;
int raw_socket_open(struct vfs_ioctx *ioctx, struct ofile *fd, int dom, int type, int proto) {
// TODO: check your privilege
struct raw_socket *r_sock = kmalloc(sizeof(struct raw_socket));
_assert(r_sock);
packet_queue_init(&r_sock->queue);
r_sock->prev = NULL;
r_sock->next = g_raw_sockets;
g_raw_sockets = r_sock;
fd->flags |= OF_SOCKET;
fd->socket.sock = r_sock;
fd->socket.domain = PF_PACKET;
fd->socket.type = SOCK_RAW;
return 0;
}
void raw_socket_close(struct vfs_ioctx *ioctx, struct ofile *fd) {
// Do nothing, I guess
}
void raw_packet_handle(struct packet *p) {
// Queue the packet for all the sockets
for (struct raw_socket *r = g_raw_sockets; r; r = r->next) {
packet_ref(p);
packet_queue_push(&r->queue, p);
}
}
+6 -7
View File
@@ -30,7 +30,7 @@ struct udp_socket {
uint32_t recv_inaddr;
struct netdev *bound; // Bound interface (all packets go to this interface if set)
struct thread *owner; // Thread to suspend on blocking operation
struct packet *pending;
struct packet_queue pending;
};
static uint16_t udp_eph_port = 32768;
@@ -48,8 +48,8 @@ struct udp_socket *udp_socket_create(void) {
sock->port = 0;
sock->recv_port = 0;
sock->owner = NULL;
sock->pending = NULL;
sock->bound = NULL;
packet_queue_init(&sock->pending);
return sock;
}
@@ -74,7 +74,7 @@ ssize_t udp_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, si
sock->owner = t;
if (!sock->pending) {
if (!sock->pending.head) {
sock->flags |= UDP_SOCKET_PENDING;
while ((sock->flags & UDP_SOCKET_PENDING)) {
@@ -84,8 +84,8 @@ ssize_t udp_socket_recv(struct vfs_ioctx *ioctx, struct ofile *fd, void *buf, si
}
// Read a single packet
p = sock->pending;
sock->pending = p->next;
p = packet_queue_pop(&sock->pending);
_assert(p);
size_t f_size = sizeof(struct eth_frame) + sizeof(struct inet_frame) + sizeof(struct udp_frame);
const void *p_data = p->data + f_size;
@@ -221,8 +221,7 @@ void udp_handle_frame(struct packet *p, struct eth_frame *eth, struct inet_frame
if (sock) {
// Add "pending" packet for this socket
packet_ref(p);
p->next = sock->pending;
sock->pending = p;
packet_queue_push(&sock->pending, p);
if (sock->flags & UDP_SOCKET_PENDING) {
sock->flags &= ~UDP_SOCKET_PENDING;