mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
netdev: cleanup and abstraction
This commit is contained in:
@@ -35,6 +35,15 @@ typedef struct {
|
||||
#define NETDEV_FLAGS_RUNNING 0x40
|
||||
#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 {
|
||||
mac_t mac;
|
||||
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
|
||||
hashtable_t arpcache;
|
||||
short flags;
|
||||
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 *_internal, netdesc_t desc, mac_t targetmac, int proto);
|
||||
const netdevops_t *ops;
|
||||
} netdev_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -83,7 +89,6 @@ 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);
|
||||
@@ -96,6 +101,8 @@ size_t ipv4_getmtu(uint32_t ip);
|
||||
uint32_t ipv4_getnetdevip(uint32_t ip);
|
||||
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 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);
|
||||
netdev_t *netdev_getdev(char *name);
|
||||
netdev_t *netdev_from_minor(uint16_t minor);
|
||||
|
||||
@@ -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.dsthw, &mac, sizeof(mac_t));
|
||||
netdesc_t desc;
|
||||
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc);
|
||||
int e = netdev->ops->allocdesc(netdev, sizeof(arpframe_t), &desc);
|
||||
if (e)
|
||||
return;
|
||||
|
||||
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() {
|
||||
@@ -229,13 +229,13 @@ static int sendrequest(netdev_t *netdev, uint32_t ip) {
|
||||
|
||||
memcpy(&frame.srchw, &netdev->mac, sizeof(mac_t));
|
||||
netdesc_t desc;
|
||||
int e = netdev->allocdesc(netdev, sizeof(arpframe_t), &desc);
|
||||
int e = netdev->ops->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);
|
||||
e = netdev->ops->sendpacket(netdev, desc, NET_BROADCAST_MAC, ETH_PROTO_ARP);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ static int dispatch_fragment(netdev_t *netdev, netdesc_t fragdesc,
|
||||
frame.framechecksum = cpu_to_be_w(checksum(&frame, sizeof(frame)));
|
||||
|
||||
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) {
|
||||
@@ -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) {
|
||||
size_t fragmentlen = (i == fragmentcount - 1) ? packetsize - devfragmentsize * (fragmentcount - 1) : devfragmentsize;
|
||||
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)
|
||||
return e;
|
||||
|
||||
|
||||
@@ -43,24 +43,23 @@ static int loopback_sendpacket(netdev_t *netdev, netdesc_t desc, mac_t targetmac
|
||||
eth_process(netdev, desc.address, desc.size);
|
||||
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() {
|
||||
return &loopbacknetdev;
|
||||
}
|
||||
|
||||
void loopback_init() {
|
||||
loopbacknetdev.mtu = 30000;
|
||||
loopbacknetdev.sendpacket = loopback_sendpacket;
|
||||
loopbacknetdev.allocdesc = loopback_allocdesc;
|
||||
loopbacknetdev.freedesc = loopback_freedesc;
|
||||
__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(hashtable_init(&loopbacknetdev.arpcache, 30) == 0);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
loopbacknetdev.mac.address[i] = 0;
|
||||
|
||||
__assert(netdev_register(&loopbacknetdev, "lo") == 0);
|
||||
}
|
||||
|
||||
@@ -250,6 +250,21 @@ netdev_t *netdev_from_minor(uint16_t 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) {
|
||||
// TODO: better allocation strategy (copy wlan's?)
|
||||
int minor = __atomic_fetch_add(¤t_minor, 1, __ATOMIC_RELAXED);
|
||||
|
||||
@@ -121,19 +121,19 @@ static int raw_send(socket_t *socket_handle, sockdesc_t *sockdesc) {
|
||||
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)
|
||||
goto leave;
|
||||
|
||||
error = iovec_iterator_copy_to_buffer(sockdesc->iovec_iterator, (void *)((uintptr_t)desc.address + desc.curroffset), sockdesc->count);
|
||||
if (error) {
|
||||
socket->netdev_binding->freedesc(socket->netdev_binding, &desc);
|
||||
socket->netdev_binding->ops->freedesc(socket->netdev_binding, &desc);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mac_t 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)
|
||||
sockdesc->donecount = sockdesc->count;
|
||||
|
||||
|
||||
@@ -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);
|
||||
sched_yield();
|
||||
|
||||
return internal->freedesc(internal, &desc);
|
||||
return internal->ops->freedesc(internal, &desc);
|
||||
}
|
||||
|
||||
// requested size doesn't account for ethernet header
|
||||
@@ -215,6 +215,12 @@ static int rtl8169_freedesc(netdev_t *netdev, netdesc_t *desc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const netdevops_t rtl8169_ops = {
|
||||
.allocdesc = rtl8169_allocdesc,
|
||||
.freedesc = rtl8169_freedesc,
|
||||
.sendpacket = rtl8169_sendpacket
|
||||
};
|
||||
|
||||
static int controller_id = 0;
|
||||
|
||||
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));
|
||||
__assert(netdev);
|
||||
netdev->netdev.mtu = 1500;
|
||||
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);
|
||||
__assert(netdev_initialize(&netdev->netdev, &rtl8169_ops, 1500, mac) == 0);
|
||||
|
||||
netdev->tx_ring = tx_ring;
|
||||
netdev->rx_ring = rx_ring;
|
||||
|
||||
@@ -151,9 +151,15 @@ static int vionet_sendpacket(netdev_t *internal, netdesc_t desc, mac_t targetmac
|
||||
sched_yield();
|
||||
|
||||
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) {
|
||||
static int id = 0;
|
||||
volatile vionetconfig_t *vionetconfig = viodevice->devconfig;
|
||||
@@ -174,13 +180,12 @@ int vionet_newdevice(viodevice_t *viodevice) {
|
||||
|
||||
vionetdev_t *netdev = alloc(sizeof(vionetdev_t));
|
||||
__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->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->txdpc, tx_dpc);
|
||||
|
||||
@@ -225,9 +230,6 @@ int vionet_newdevice(viodevice_t *viodevice) {
|
||||
*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]);
|
||||
|
||||
char name[10];
|
||||
|
||||
+17
-18
@@ -25,11 +25,6 @@ typedef struct {
|
||||
// TODO: handle hotplug
|
||||
// TODO: in u80211_drv *_tx_buffer ops, pass device handle
|
||||
// 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 int allocate_id(void) {
|
||||
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));
|
||||
}
|
||||
|
||||
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) {
|
||||
wlan_device_t *wlan = alloc(sizeof(wlan_device_t));
|
||||
if (wlan == NULL)
|
||||
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->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;
|
||||
memcpy(&wlan->netdev.mac, &drv_metadata->mac_address, 6);
|
||||
if (hashtable_init(&wlan->netdev.arpcache, 30)) {
|
||||
free(wlan);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
wlan->id = allocate_id();
|
||||
if (wlan->id == -1) {
|
||||
hashtable_destroy(&wlan->netdev.arpcache);
|
||||
netdev_destroy(&wlan->netdev);
|
||||
free(wlan);
|
||||
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);
|
||||
if (status != U80211_STATUS_SUCCESS) {
|
||||
free_id(wlan->id);
|
||||
hashtable_destroy(&wlan->netdev.arpcache);
|
||||
netdev_destroy(&wlan->netdev);
|
||||
free(wlan);
|
||||
return u80211_status_to_errno(status);
|
||||
}
|
||||
|
||||
char name[10];
|
||||
snprintf(name, 10, "wlan%d", wlan->id);
|
||||
int error = netdev_register(&wlan->netdev, name);
|
||||
error = netdev_register(&wlan->netdev, name);
|
||||
if (error) {
|
||||
u80211_unregister_device(wlan->u80211_device);
|
||||
free_id(wlan->id);
|
||||
hashtable_destroy(&wlan->netdev.arpcache);
|
||||
netdev_destroy(&wlan->netdev);
|
||||
free(wlan);
|
||||
return error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user