diff --git a/kernel-src/include/kernel/net.h b/kernel-src/include/kernel/net.h index e4f321db..7f9029a9 100644 --- a/kernel-src/include/kernel/net.h +++ b/kernel-src/include/kernel/net.h @@ -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); diff --git a/kernel-src/io/net/arp.c b/kernel-src/io/net/arp.c index 1e37b895..62ccdbc4 100644 --- a/kernel-src/io/net/arp.c +++ b/kernel-src/io/net/arp.c @@ -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; } diff --git a/kernel-src/io/net/ipv4.c b/kernel-src/io/net/ipv4.c index d8a79e12..3c1d6a49 100644 --- a/kernel-src/io/net/ipv4.c +++ b/kernel-src/io/net/ipv4.c @@ -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; diff --git a/kernel-src/io/net/loopback.c b/kernel-src/io/net/loopback.c index 05868f89..6c42510b 100644 --- a/kernel-src/io/net/loopback.c +++ b/kernel-src/io/net/loopback.c @@ -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); } diff --git a/kernel-src/io/net/netdev.c b/kernel-src/io/net/netdev.c index d8f96117..b0b799d3 100644 --- a/kernel-src/io/net/netdev.c +++ b/kernel-src/io/net/netdev.c @@ -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); diff --git a/kernel-src/io/net/raw.c b/kernel-src/io/net/raw.c index 2918ff8b..cfe64046 100644 --- a/kernel-src/io/net/raw.c +++ b/kernel-src/io/net/raw.c @@ -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; diff --git a/kernel-src/io/net/rtl8169.c b/kernel-src/io/net/rtl8169.c index d03f9611..8edbb038 100644 --- a/kernel-src/io/net/rtl8169.c +++ b/kernel-src/io/net/rtl8169.c @@ -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; diff --git a/kernel-src/io/net/vionet.c b/kernel-src/io/net/vionet.c index 1c48fe76..bbe3b32b 100644 --- a/kernel-src/io/net/vionet.c +++ b/kernel-src/io/net/vionet.c @@ -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]; diff --git a/kernel-src/io/net/wlan.c b/kernel-src/io/net/wlan.c index 21eb7abc..08bc07e1 100644 --- a/kernel-src/io/net/wlan.c +++ b/kernel-src/io/net/wlan.c @@ -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; }