Files
kernel/net/net.c
T
2020-07-05 23:16:10 +03:00

146 lines
3.3 KiB
C

#include "sys/mem/phys.h"
#include "arch/amd64/cpu.h"
#include "user/socket.h"
#include "sys/thread.h"
#include "user/errno.h"
#include "sys/assert.h"
#include "sys/string.h"
#include "sys/sched.h"
#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/if.h"
//static struct thread netd_thread = {0};
static struct packet_queue g_rxq;
static void packet_free(struct packet *p);
static inline void net_handle_packet(struct packet *p) {
// XXX: Dummy handler until I rewrite networking properly
}
//static void net_daemon(void) {
// struct packet *p;
// uintptr_t irq;
//
// while (1) {
// if (!g_rxq.head) {
// // TODO: old code with sleep led to huge delays
// asm volatile ("sti; hlt");
// continue;
// }
//
// p = packet_queue_pop(&g_rxq);
// _assert(p);
// net_handle_packet(p);
//
// packet_unref(p);
// }
//}
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);
qh->next = NULL;
uintptr_t irq;
spin_lock_irqsave(&pq->lock, &irq);
if (pq->tail) {
pq->tail->next = qh;
} else {
pq->head = qh;
}
qh->prev = pq->tail;
pq->tail = qh;
spin_release_irqrestore(&pq->lock, &irq);
}
struct packet *packet_queue_pop(struct packet_queue *pq) {
uintptr_t irq;
spin_lock_irqsave(&pq->lock, &irq);
struct packet_qh *qh = pq->head;
_assert(qh);
pq->head = qh->next;
if (!pq->head) {
pq->tail = NULL;
}
spin_release_irqrestore(&pq->lock, &irq);
struct packet *p = qh->packet;
kfree(qh);
return p;
}
void packet_queue_init(struct packet_queue *pq) {
pq->lock = 0;
pq->head = NULL;
pq->tail = NULL;
}
struct packet *packet_create(size_t size) {
struct packet *packet;
uintptr_t page = mm_phys_alloc_page();
_assert(page != MM_NADDR);
packet = (struct packet *) MM_VIRTUALIZE(page);
packet->refcount = 0;
packet->size = size;
return packet;
}
static void packet_free(struct packet *p) {
uintptr_t page = MM_PHYS(p);
mm_phys_free_page(page);
}
void packet_ref(struct packet *p) {
++p->refcount;
}
void packet_unref(struct packet *p) {
_assert(p->refcount);
--p->refcount;
if (!p->refcount) {
packet_free(p);
}
}
int net_receive(struct netdev *dev, const void *data, size_t len) {
if (len > PACKET_DATA_MAX) {
kwarn("%s: dropping large packet (%u)\n", dev->name, len);
return -1;
}
struct packet *p = packet_create(len);
// TODO: maybe information like "Physical match", "Multicast" or "Broadcast"
// would be useful to store in packet
memcpy(p->data, data, len);
p->dev = dev;
packet_ref(p);
//packet_queue_push(&g_rxq, p);
return 0;
}
void net_init(void) {
// XXX: Dummy
}
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);
}