netdev: cleanup and abstraction

This commit is contained in:
Matheus
2026-09-14 09:47:07 -03:00
parent b1c82ae6af
commit f0dc54e027
9 changed files with 80 additions and 57 deletions
+12 -5
View File
@@ -35,6 +35,15 @@ typedef struct {
#define NETDEV_FLAGS_RUNNING 0x40 #define NETDEV_FLAGS_RUNNING 0x40
#define NETDEV_FLAGS_WLAN 0x80 #define NETDEV_FLAGS_WLAN 0x80
struct netdev_t;
typedef struct {
int (*allocdesc)(struct netdev_t *netdev, size_t requestedsize, netdesc_t *desc);
int (*freedesc)(struct netdev_t *netdev, netdesc_t *desc);
// consumes desc regardless of the returned status
int (*sendpacket)(struct netdev_t *netdev, netdesc_t desc, mac_t targetmac, int proto);
} netdevops_t;
typedef struct netdev_t { typedef struct netdev_t {
mac_t mac; mac_t mac;
int ifindex; int ifindex;
@@ -43,10 +52,7 @@ typedef struct netdev_t {
int ipcurrid; // XXX This is defined as something per peer. However, having only one of these *should* work for most cases int ipcurrid; // XXX This is defined as something per peer. However, having only one of these *should* work for most cases
hashtable_t arpcache; hashtable_t arpcache;
short flags; short flags;
int (*allocdesc)(struct netdev_t *netdev, size_t requestedsize, netdesc_t *desc); const netdevops_t *ops;
int (*freedesc)(struct netdev_t *netdev, netdesc_t *desc);
// consumes desc regardless of the returned status
int (*sendpacket)(struct netdev_t *_internal, netdesc_t desc, mac_t targetmac, int proto);
} netdev_t; } netdev_t;
typedef struct { typedef struct {
@@ -83,7 +89,6 @@ void arp_init();
void ipv4_init(); void ipv4_init();
void udp_init(); void udp_init();
void tcp_init(); void tcp_init();
void netdev_init();
void loopback_init(); void loopback_init();
netdev_t *loopback_device(); netdev_t *loopback_device();
void udp_process(netdev_t *netdev, void *buffer, uint32_t ip); void udp_process(netdev_t *netdev, void *buffer, uint32_t ip);
@@ -96,6 +101,8 @@ size_t ipv4_getmtu(uint32_t ip);
uint32_t ipv4_getnetdevip(uint32_t ip); uint32_t ipv4_getnetdevip(uint32_t ip);
void ipv4_process(netdev_t *netdev, void *nextbuff, size_t size); void ipv4_process(netdev_t *netdev, void *nextbuff, size_t size);
int ipv4_addroute(netdev_t *netdev, uint32_t addr, uint32_t gateway, uint32_t mask, int weight); int ipv4_addroute(netdev_t *netdev, uint32_t addr, uint32_t gateway, uint32_t mask, int weight);
int netdev_initialize(netdev_t *netdev, const netdevops_t *ops, size_t mtu, mac_t mac);
void netdev_destroy(netdev_t *netdev);
int netdev_register(netdev_t *netdev, char *name); int netdev_register(netdev_t *netdev, char *name);
netdev_t *netdev_getdev(char *name); netdev_t *netdev_getdev(char *name);
netdev_t *netdev_from_minor(uint16_t minor); netdev_t *netdev_from_minor(uint16_t minor);
+4 -4
View File
@@ -140,13 +140,13 @@ static void send_reply(netdev_t *netdev, uint32_t ip, mac_t mac) {
memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t)); memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t));
memcpy(&frame.dsthw, &mac, sizeof(mac_t)); memcpy(&frame.dsthw, &mac, sizeof(mac_t));
netdesc_t desc; netdesc_t desc;
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc); int e = netdev->ops->allocdesc(netdev, sizeof(arpframe_t), &desc);
if (e) if (e)
return; return;
memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame)); memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame));
netdev->sendpacket(netdev, desc, mac, ETH_PROTO_ARP); netdev->ops->sendpacket(netdev, desc, mac, ETH_PROTO_ARP);
} }
static void handlerthreadfn() { static void handlerthreadfn() {
@@ -229,13 +229,13 @@ static int sendrequest(netdev_t *netdev, uint32_t ip) {
memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t)); memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t));
netdesc_t desc; netdesc_t desc;
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc); int e = netdev->ops->allocdesc(netdev, sizeof(arpframe_t), &desc);
if (e) if (e)
return e; return e;
memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame)); memcpy((void *)((uintptr_t)desc.address + desc.curroffset), &frame, sizeof(frame));
e = netdev->sendpacket(netdev, desc, NET_BROADCAST_MAC, ETH_PROTO_ARP); e = netdev->ops->sendpacket(netdev, desc, NET_BROADCAST_MAC, ETH_PROTO_ARP);
return e; return e;
} }
+2 -2
View File
@@ -121,7 +121,7 @@ static int dispatch_fragment(netdev_t *netdev, netdesc_t fragdesc,
frame.framechecksum = cpu_to_be_w(checksum(&frame, sizeof(frame))); frame.framechecksum = cpu_to_be_w(checksum(&frame, sizeof(frame)));
memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset), &frame, sizeof(ipv4frame_t)); memcpy((void *)((uintptr_t)fragdesc.address + fragdesc.curroffset), &frame, sizeof(ipv4frame_t));
return netdev->sendpacket(netdev, fragdesc, mac, ETH_PROTO_IP); return netdev->ops->sendpacket(netdev, fragdesc, mac, ETH_PROTO_IP);
} }
void ipv4_process(netdev_t *netdev, void *buff, size_t size) { void ipv4_process(netdev_t *netdev, void *buff, size_t size) {
@@ -212,7 +212,7 @@ int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, net
for (int i = 0; i < fragmentcount; ++i) { for (int i = 0; i < fragmentcount; ++i) {
size_t fragmentlen = (i == fragmentcount - 1) ? packetsize - devfragmentsize * (fragmentcount - 1) : devfragmentsize; size_t fragmentlen = (i == fragmentcount - 1) ? packetsize - devfragmentsize * (fragmentcount - 1) : devfragmentsize;
netdesc_t fragdesc; netdesc_t fragdesc;
int e = netdev->allocdesc(netdev, fragmentlen + sizeof(ipv4frame_t), &fragdesc); int e = netdev->ops->allocdesc(netdev, fragmentlen + sizeof(ipv4frame_t), &fragdesc);
if (e) if (e)
return e; return e;
+8 -9
View File
@@ -43,24 +43,23 @@ static int loopback_sendpacket(netdev_t *netdev, netdesc_t desc, mac_t targetmac
eth_process(netdev, desc.address, desc.size); eth_process(netdev, desc.address, desc.size);
interrupt_loweripl(ipl); interrupt_loweripl(ipl);
return netdev->freedesc(netdev, &desc); 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() { netdev_t *loopback_device() {
return &loopbacknetdev; return &loopbacknetdev;
} }
void loopback_init() { void loopback_init() {
loopbacknetdev.mtu = 30000; __assert(netdev_initialize(&loopbacknetdev, &loopback_ops, 30000, (mac_t){0}) == 0);
loopbacknetdev.sendpacket = loopback_sendpacket;
loopbacknetdev.allocdesc = loopback_allocdesc;
loopbacknetdev.freedesc = loopback_freedesc;
loopbacknetdev.ip = 0x7f000001; loopbacknetdev.ip = 0x7f000001;
loopbacknetdev.flags = NETDEV_FLAGS_UP | NETDEV_FLAGS_LOOPBACK | NETDEV_FLAGS_RUNNING; loopbacknetdev.flags = NETDEV_FLAGS_UP | NETDEV_FLAGS_LOOPBACK | NETDEV_FLAGS_RUNNING;
__assert(hashtable_init(&loopbacknetdev.arpcache, 30) == 0);
for (int i = 0; i < 6; ++i)
loopbacknetdev.mac.address[i] = 0;
__assert(netdev_register(&loopbacknetdev, "lo") == 0); __assert(netdev_register(&loopbacknetdev, "lo") == 0);
} }
+15
View File
@@ -250,6 +250,21 @@ netdev_t *netdev_from_minor(uint16_t minor) {
return minors[minor]; return minors[minor];
} }
int netdev_initialize(netdev_t *netdev, const netdevops_t *ops, size_t mtu, mac_t mac) {
int error = hashtable_init(&netdev->arpcache, 30);
if (error)
return error;
netdev->ops = ops;
netdev->mtu = mtu;
netdev->mac = mac;
return 0;
}
void netdev_destroy(netdev_t *netdev) {
hashtable_destroy(&netdev->arpcache);
}
int netdev_register(netdev_t *netdev, char *name) { int netdev_register(netdev_t *netdev, char *name) {
// TODO: better allocation strategy (copy wlan's?) // TODO: better allocation strategy (copy wlan's?)
int minor = __atomic_fetch_add(&current_minor, 1, __ATOMIC_RELAXED); int minor = __atomic_fetch_add(&current_minor, 1, __ATOMIC_RELAXED);
+3 -3
View File
@@ -121,19 +121,19 @@ static int raw_send(socket_t *socket_handle, sockdesc_t *sockdesc) {
goto leave; goto leave;
} }
error = socket->netdev_binding->allocdesc(socket->netdev_binding, sockdesc->count, &desc); error = socket->netdev_binding->ops->allocdesc(socket->netdev_binding, sockdesc->count, &desc);
if (error) if (error)
goto leave; goto leave;
error = iovec_iterator_copy_to_buffer(sockdesc->iovec_iterator, (void *)((uintptr_t)desc.address + desc.curroffset), sockdesc->count); error = iovec_iterator_copy_to_buffer(sockdesc->iovec_iterator, (void *)((uintptr_t)desc.address + desc.curroffset), sockdesc->count);
if (error) { if (error) {
socket->netdev_binding->freedesc(socket->netdev_binding, &desc); socket->netdev_binding->ops->freedesc(socket->netdev_binding, &desc);
goto leave; goto leave;
} }
mac_t target; mac_t target;
memcpy(&target, sockdesc->addr->raw.mac, sizeof(target)); memcpy(&target, sockdesc->addr->raw.mac, sizeof(target));
error = socket->netdev_binding->sendpacket(socket->netdev_binding, desc, target, socket->proto); error = socket->netdev_binding->ops->sendpacket(socket->netdev_binding, desc, target, socket->proto);
if (error == 0) if (error == 0)
sockdesc->donecount = sockdesc->count; sockdesc->donecount = sockdesc->count;
+8 -7
View File
@@ -193,7 +193,7 @@ static int rtl8169_sendpacket(netdev_t *internal, netdesc_t desc, mac_t target,
spinlock_release_lower_ipl(&netdev->tx_lock, ipl); spinlock_release_lower_ipl(&netdev->tx_lock, ipl);
sched_yield(); sched_yield();
return internal->freedesc(internal, &desc); return internal->ops->freedesc(internal, &desc);
} }
// requested size doesn't account for ethernet header // requested size doesn't account for ethernet header
@@ -215,6 +215,12 @@ static int rtl8169_freedesc(netdev_t *netdev, netdesc_t *desc) {
return 0; return 0;
} }
static const netdevops_t rtl8169_ops = {
.allocdesc = rtl8169_allocdesc,
.freedesc = rtl8169_freedesc,
.sendpacket = rtl8169_sendpacket
};
static int controller_id = 0; static int controller_id = 0;
static void init_controller(pcienum_t *pci_enum) { static void init_controller(pcienum_t *pci_enum) {
@@ -324,12 +330,7 @@ static void init_controller(pcienum_t *pci_enum) {
rtl8169dev_t *netdev = alloc(sizeof(rtl8169dev_t)); rtl8169dev_t *netdev = alloc(sizeof(rtl8169dev_t));
__assert(netdev); __assert(netdev);
netdev->netdev.mtu = 1500; __assert(netdev_initialize(&netdev->netdev, &rtl8169_ops, 1500, mac) == 0);
netdev->netdev.sendpacket = rtl8169_sendpacket;
netdev->netdev.allocdesc = rtl8169_allocdesc;
netdev->netdev.freedesc = rtl8169_freedesc;
memcpy(&netdev->netdev.mac, &mac, sizeof(mac));
__assert(hashtable_init(&netdev->netdev.arpcache, 30) == 0);
netdev->tx_ring = tx_ring; netdev->tx_ring = tx_ring;
netdev->rx_ring = rx_ring; netdev->rx_ring = rx_ring;
+11 -9
View File
@@ -151,9 +151,15 @@ static int vionet_sendpacket(netdev_t *internal, netdesc_t desc, mac_t targetmac
sched_yield(); sched_yield();
interrupt_set(intstatus); interrupt_set(intstatus);
return internal->freedesc(internal, &desc); return internal->ops->freedesc(internal, &desc);
} }
static const netdevops_t vionet_ops = {
.allocdesc = vionet_allocdesc,
.freedesc = vionet_freedesc,
.sendpacket = vionet_sendpacket
};
int vionet_newdevice(viodevice_t *viodevice) { int vionet_newdevice(viodevice_t *viodevice) {
static int id = 0; static int id = 0;
volatile vionetconfig_t *vionetconfig = viodevice->devconfig; volatile vionetconfig_t *vionetconfig = viodevice->devconfig;
@@ -174,13 +180,12 @@ int vionet_newdevice(viodevice_t *viodevice) {
vionetdev_t *netdev = alloc(sizeof(vionetdev_t)); vionetdev_t *netdev = alloc(sizeof(vionetdev_t));
__assert(netdev); __assert(netdev);
mac_t mac;
for (int i = 0; i < 6; ++i)
mac.address[i] = vionetconfig->mac[i];
__assert(netdev_initialize(&netdev->netdev, &vionet_ops, 1500, mac) == 0);
netdev->viodevice = viodevice; netdev->viodevice = viodevice;
netdev->id = id++; netdev->id = id++;
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);
dpc_prepare(&netdev->rxdpc, rx_dpc); dpc_prepare(&netdev->rxdpc, rx_dpc);
dpc_prepare(&netdev->txdpc, tx_dpc); dpc_prepare(&netdev->txdpc, tx_dpc);
@@ -225,9 +230,6 @@ int vionet_newdevice(viodevice_t *viodevice) {
*netdev->rxqueue.notify = 0; *netdev->rxqueue.notify = 0;
} }
for (int i = 0; i < 6; ++i)
netdev->netdev.mac.address[i] = vionetconfig->mac[i];
printf("vionet%d: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev->id, netdev->netdev.mac.address[0], netdev->netdev.mac.address[1], netdev->netdev.mac.address[2], netdev->netdev.mac.address[3], netdev->netdev.mac.address[4], netdev->netdev.mac.address[5]); printf("vionet%d: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev->id, netdev->netdev.mac.address[0], netdev->netdev.mac.address[1], netdev->netdev.mac.address[2], netdev->netdev.mac.address[3], netdev->netdev.mac.address[4], netdev->netdev.mac.address[5]);
char name[10]; char name[10];
+17 -18
View File
@@ -25,11 +25,6 @@ typedef struct {
// TODO: handle hotplug // TODO: handle hotplug
// TODO: in u80211_drv *_tx_buffer ops, pass device handle // TODO: in u80211_drv *_tx_buffer ops, pass device handle
// TODO: change how netdesc_t is handled in kernel overall (?) // TODO: change how netdesc_t is handled in kernel overall (?)
// TODO: general netdev cleanup:
// - use struct ops instead of having function pointers in netdev struct
// - proper initialize() function
// - proper destroy() function
static uint64_t id_bitmap; static uint64_t id_bitmap;
static int allocate_id(void) { static int allocate_id(void) {
for (;;) { for (;;) {
@@ -228,28 +223,32 @@ static int wlan_send_packet(netdev_t *netdev, netdesc_t desc, mac_t target, int
return u80211_status_to_errno(u80211_transmit_buffer(wlan->u80211_device, &descriptor)); return u80211_status_to_errno(u80211_transmit_buffer(wlan->u80211_device, &descriptor));
} }
static const netdevops_t netdev_ops = {
.allocdesc = wlan_alloc_desc,
.freedesc = wlan_free_desc,
.sendpacket = wlan_send_packet
};
int wlan_register(void *handle, const u80211_drv_device_metadata_t *drv_metadata, const u80211_drv_device_ops_t *drv_ops, u80211_drv_network_device_handle_t *network_device) { int wlan_register(void *handle, const u80211_drv_device_metadata_t *drv_metadata, const u80211_drv_device_ops_t *drv_ops, u80211_drv_network_device_handle_t *network_device) {
wlan_device_t *wlan = alloc(sizeof(wlan_device_t)); wlan_device_t *wlan = alloc(sizeof(wlan_device_t));
if (wlan == NULL) if (wlan == NULL)
return ENOMEM; return ENOMEM;
mac_t mac;
memcpy(&mac, &drv_metadata->mac_address, sizeof(mac));
int error = netdev_initialize(&wlan->netdev, &netdev_ops, WLAN_MTU, mac);
if (error) {
free(wlan);
return error;
}
wlan->driver_handle = handle; wlan->driver_handle = handle;
wlan->ops = drv_ops; wlan->ops = drv_ops;
wlan->netdev.mtu = WLAN_MTU;
wlan->netdev.sendpacket = wlan_send_packet;
wlan->netdev.allocdesc = wlan_alloc_desc;
wlan->netdev.freedesc = wlan_free_desc;
wlan->netdev.flags = NETDEV_FLAGS_WLAN | NETDEV_FLAGS_UP | NETDEV_FLAGS_BROADCAST | NETDEV_FLAGS_RUNNING; wlan->netdev.flags = NETDEV_FLAGS_WLAN | NETDEV_FLAGS_UP | NETDEV_FLAGS_BROADCAST | NETDEV_FLAGS_RUNNING;
memcpy(&wlan->netdev.mac, &drv_metadata->mac_address, 6);
if (hashtable_init(&wlan->netdev.arpcache, 30)) {
free(wlan);
return ENOMEM;
}
wlan->id = allocate_id(); wlan->id = allocate_id();
if (wlan->id == -1) { if (wlan->id == -1) {
hashtable_destroy(&wlan->netdev.arpcache); netdev_destroy(&wlan->netdev);
free(wlan); free(wlan);
return EAGAIN; return EAGAIN;
} }
@@ -261,18 +260,18 @@ int wlan_register(void *handle, const u80211_drv_device_metadata_t *drv_metadata
int status = u80211_register_device(&metadata, &ops, wlan, &wlan->u80211_device); int status = u80211_register_device(&metadata, &ops, wlan, &wlan->u80211_device);
if (status != U80211_STATUS_SUCCESS) { if (status != U80211_STATUS_SUCCESS) {
free_id(wlan->id); free_id(wlan->id);
hashtable_destroy(&wlan->netdev.arpcache); netdev_destroy(&wlan->netdev);
free(wlan); free(wlan);
return u80211_status_to_errno(status); return u80211_status_to_errno(status);
} }
char name[10]; char name[10];
snprintf(name, 10, "wlan%d", wlan->id); snprintf(name, 10, "wlan%d", wlan->id);
int error = netdev_register(&wlan->netdev, name); error = netdev_register(&wlan->netdev, name);
if (error) { if (error) {
u80211_unregister_device(wlan->u80211_device); u80211_unregister_device(wlan->u80211_device);
free_id(wlan->id); free_id(wlan->id);
hashtable_destroy(&wlan->netdev.arpcache); netdev_destroy(&wlan->netdev);
free(wlan); free(wlan);
return error; return error;
} }