Files
Astral/kernel-src/io/net/loopback.c
2026-09-14 09:47:07 -03:00

68 lines
1.8 KiB
C

#include <kernel/virtio.h>
#include <logging.h>
#include <kernel/page.h>
#include <kernel/eth.h>
#include <kernel/net.h>
#include <hashtable.h>
#include <arch/cpu.h>
#include <kernel/init.h>
#include <kernel/interrupt.h>
static netdev_t loopbacknetdev;
// requested size doesn't account for ethernet header or the virtio header
static int loopback_allocdesc(netdev_t *netdev, size_t requestedsize, netdesc_t *desc) {
__assert(requestedsize <= netdev->mtu);
desc->address = alloc(requestedsize + sizeof(ethframe_t));
if (desc->address == NULL)
return ENOMEM;
desc->size = requestedsize + sizeof(ethframe_t);
desc->curroffset = sizeof(ethframe_t);
return 0;
}
static int loopback_freedesc(netdev_t *netdev, netdesc_t *desc) {
free(desc->address);
return 0;
}
static int loopback_sendpacket(netdev_t *netdev, netdesc_t desc, mac_t targetmac, int proto) {
desc.curroffset = 0;
ethframe_t ethframe = {
.type = cpu_to_be_w(proto)
};
mac_t broadcast = NET_BROADCAST_MAC;
memcpy(&ethframe.source, &netdev->mac, sizeof(mac_t));
memcpy(&ethframe.destination, &broadcast, sizeof(mac_t));
memcpy(desc.address, &ethframe, sizeof(ethframe_t));
long ipl = interrupt_raiseipl(IPL_DPC);
eth_process(netdev, desc.address, desc.size);
interrupt_loweripl(ipl);
return netdev->ops->freedesc(netdev, &desc);
}
static const netdevops_t loopback_ops = {
.allocdesc = loopback_allocdesc,
.freedesc = loopback_freedesc,
.sendpacket = loopback_sendpacket
};
netdev_t *loopback_device() {
return &loopbacknetdev;
}
void loopback_init() {
__assert(netdev_initialize(&loopbacknetdev, &loopback_ops, 30000, (mac_t){0}) == 0);
loopbacknetdev.ip = 0x7f000001;
loopbacknetdev.flags = NETDEV_FLAGS_UP | NETDEV_FLAGS_LOOPBACK | NETDEV_FLAGS_RUNNING;
__assert(netdev_register(&loopbacknetdev, "lo") == 0);
}
INIT_ROUTINE_DEFINE(loopback, INIT_ROUTINE_FLAGS_NONE, loopback_init, devfs);