mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
netdev: freeing of netdescs
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user