netdev: freeing of netdescs

This commit is contained in:
Matheus
2024-06-03 21:55:52 -03:00
parent 4c0940828c
commit 7053ed68af
5 changed files with 50 additions and 20 deletions
+7 -1
View File
@@ -28,7 +28,8 @@ typedef struct netdev_t {
size_t mtu;
uint32_t ip;
hashtable_t arpcache;
int (*allocdesc)(size_t requestedsize, netdesc_t *desc);
int (*allocdesc)(struct netdev_t *netdev, size_t requestedsize, netdesc_t *desc);
int (*freedesc)(struct netdev_t *netdev, netdesc_t *desc);
int (*sendpacket)(struct netdev_t *_internal, netdesc_t desc, mac_t targetmac, int proto);
} netdev_t;
@@ -61,20 +62,25 @@ typedef struct {
#define MAC_EQUAL(m1,m2) (memcmp(m1, m2, sizeof(mac_t)) == 0)
#define IPV4_PROTO_TCP 0x06
#define IPV4_PROTO_UDP 0x11
#define IPV4_BROADCAST_ADDRESS 0xffffffff
void arp_init();
void ipv4_init();
void udp_init();
void tcp_init();
void netdev_init();
void loopback_init();
netdev_t *loopback_device();
void udp_process(netdev_t *netdev, void *buffer, uint32_t ip);
void arp_process(netdev_t *netdev, void *buffer);
void tcp_process(netdev_t *netdev, void *buffer, ipv4frame_t *ipv4frame);
int arp_lookup(netdev_t *netdev, uint32_t ip, mac_t *mac);
int udp_sendpacket(void *buffer, size_t packetsize, uint32_t ip, uint16_t srcport, uint16_t dstport, netdev_t *broadcastdev);
int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, netdev_t *broadcastdev);
size_t ipv4_getmtu(uint32_t ip);
uint32_t ipv4_getnetdevip(uint32_t ip);
void ipv4_process(netdev_t *netdev, void *nextbuff);
int ipv4_addroute(netdev_t *netdev, uint32_t addr, uint32_t gateway, uint32_t mask, int weight);
int netdev_register(netdev_t *netdev, char *name);
+21 -11
View File
@@ -135,14 +135,14 @@ static void send_reply(netdev_t *netdev, uint32_t ip, mac_t mac) {
memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t));
memcpy(&frame.dsthw, &mac, sizeof(mac_t));
netdesc_t desc;
int e = netdev->allocdesc(sizeof(arpframe_t), &desc);
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc);
if (e)
return;
memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame));
e = netdev->sendpacket(netdev, desc, mac, ETH_PROTO_ARP);
// TODO free netdesc
netdev->freedesc(netdev, &desc);
}
static void handlerthreadfn() {
@@ -172,15 +172,26 @@ static void handlerthreadfn() {
}
}
// executed in dpc context
void arp_process(netdev_t *netdev, void *buffer) {
arpframe_t *frame = buffer;
__assert(frame->hwtype == cpu_to_be_w(1)); // ethernet
__assert(frame->protocoltype == cpu_to_be_w(0x800)); // ip
__assert(frame->hwlen == 6);
__assert(frame->ptlen == 4);
__assert(MAC_EQUAL(&frame->dsthw, &netdev->mac));
if (frame->hwtype != cpu_to_be_w(1)) // ethernet
return;
if (frame->protocoltype != cpu_to_be_w(0x800)) // ip
return;
if (frame->hwlen != 6)
return;
if (frame->ptlen != 4)
return;
if (be_to_cpu_w(frame->opcode) == OPCODE_REPLY && MAC_EQUAL(&frame->dsthw, &netdev->mac) == false)
return;
if (be_to_cpu_w(frame->opcode) == OPCODE_REQUEST && be_to_cpu_d(frame->dstpt) != netdev->ip)
return;
bufferentry_t entry = {
.opcode = cpu_to_be_w(frame->opcode),
@@ -209,14 +220,14 @@ static int sendrequest(netdev_t *netdev, uint32_t ip) {
memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t));
netdesc_t desc;
int e = netdev->allocdesc(sizeof(arpframe_t), &desc);
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc);
if (e)
return e;
memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame));
e = netdev->sendpacket(netdev, desc, NET_BROADCAST_MAC, ETH_PROTO_ARP);
// TODO free netdesc
netdev->freedesc(netdev, &desc);
return e;
}
@@ -231,7 +242,6 @@ int arp_lookup(netdev_t *netdev, uint32_t ip, mac_t *mac) {
if (e)
goto cleanup;
// wait
// TODO wait on an event instead of looping on a yield (ok for now, but might cause slowdows in the future)
+3 -3
View File
@@ -166,7 +166,7 @@ int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, net
if (ip != IPV4_BROADCAST_ADDRESS) {
routingentry_t entry = getroute(ip);
if (entry.netdev == NULL)
return 0; // if a packet can't be routed to anywhere just pretend it was sent somewhere
return ENETUNREACH;
int error = arp_lookup(entry.netdev, entry.gateway ? entry.gateway : ip, &mac);
if (error)
@@ -187,14 +187,14 @@ int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, net
for (int i = 0; i < fragmentcount; ++i) {
size_t fragmentlen = (i == fragmentcount - 1) ? packetsize - devfragmentsize * (fragmentcount - 1) : devfragmentsize;
netdesc_t fragdesc;
int e = netdev->allocdesc(fragmentlen + sizeof(ipv4frame_t), &fragdesc);
int e = netdev->allocdesc(netdev, fragmentlen + sizeof(ipv4frame_t), &fragdesc);
if (e)
return e;
memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset + sizeof(ipv4frame_t)), (void *)((uintptr_t)buffer + i * devfragmentsize), fragmentlen);
e = dispatch_fragment(netdev, fragdesc, i * devfragmentsize, fragmentlen, 0x1234, ip, mac, proto, i == fragmentcount - 1);
// TODO unallocate desc
netdev->freedesc(netdev, &fragdesc);
if (e)
return e;
}
+8 -1
View File
@@ -13,7 +13,8 @@ static void rx_dpc(context_t *context, dpcarg_t arg) {
}
// requested size doesn't account for ethernet header or the virtio header
static int loopback_allocdesc(size_t requestedsize, netdesc_t *desc) {
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;
@@ -23,6 +24,11 @@ static int loopback_allocdesc(size_t requestedsize, netdesc_t *desc) {
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 = {
@@ -49,6 +55,7 @@ void loopback_init() {
loopbacknetdev.mtu = 30000;
loopbacknetdev.sendpacket = loopback_sendpacket;
loopbacknetdev.allocdesc = loopback_allocdesc;
loopbacknetdev.freedesc = loopback_freedesc;
loopbacknetdev.ip = 0x7f000001;
__assert(hashtable_init(&loopbacknetdev.arpcache, 30) == 0);
+11 -4
View File
@@ -67,9 +67,9 @@ static void tx_dpc(context_t *context, dpcarg_t arg) {
while (netdev->txqueue.lastusedindex != VIO_QUEUE_DEV_IDX(&netdev->txqueue)) {
int idx = netdev->txqueue.lastusedindex++ % netdev->txqueue.size;
int buffidx = VIO_QUEUE_DEV_RING(&netdev->txqueue)[idx].index;
__assert(netdev->txwait[buffidx / 2]);
sched_wakeup(netdev->txwait[buffidx / 2], SCHED_WAKEUP_REASON_NORMAL);
netdev->txwait[buffidx / 2] = NULL;
__assert(netdev->txwait[buffidx]);
sched_wakeup(netdev->txwait[buffidx], SCHED_WAKEUP_REASON_NORMAL);
netdev->txwait[buffidx] = NULL;
buffers[buffidx].address = 0;
semaphore_signal(&netdev->txsem);
}
@@ -86,7 +86,8 @@ static void tx_irq(isr_t *isr, context_t *context) {
#define PREFIX_SIZE (sizeof(ethframe_t) + sizeof(vioframe_t))
// requested size doesn't account for ethernet header or the virtio header
static int vionet_allocdesc(size_t requestedsize, netdesc_t *desc) {
static int vionet_allocdesc(netdev_t *netdev, size_t requestedsize, netdesc_t *desc) {
__assert(requestedsize <= netdev->mtu);
size_t truesize = PREFIX_SIZE + requestedsize;
void *phys = pmm_allocpage(PMM_SECTION_DEFAULT);
if (phys == NULL)
@@ -98,6 +99,11 @@ static int vionet_allocdesc(size_t requestedsize, netdesc_t *desc) {
return 0;
}
static int vionet_freedesc(netdev_t *netdev, netdesc_t *desc) {
pmm_release(FROM_HHDM(desc->address));
return 0;
}
static int vionet_sendpacket(netdev_t *internal, netdesc_t desc, mac_t targetmac, int proto) {
vionetdev_t *netdev = (vionetdev_t *)internal;
vioframe_t vioframe = {
@@ -175,6 +181,7 @@ int vionet_newdevice(viodevice_t *viodevice) {
netdev->netdev.mtu = 1500;
netdev->netdev.sendpacket = vionet_sendpacket;
netdev->netdev.allocdesc = vionet_allocdesc;
netdev->netdev.freedesc = vionet_freedesc;
__assert(hashtable_init(&netdev->netdev.arpcache, 30) == 0);
// initialize queues