diff --git a/kernel-src/arch/x86-64/main.c b/kernel-src/arch/x86-64/main.c index f8ebdf25..ad5e4f7f 100644 --- a/kernel-src/arch/x86-64/main.c +++ b/kernel-src/arch/x86-64/main.c @@ -69,6 +69,7 @@ void kernel_entry() { ext2_init(); netdev_init(); + loopback_init(); arp_init(); ipv4_init(); udp_init(); diff --git a/kernel-src/include/kernel/net.h b/kernel-src/include/kernel/net.h index 0ba534d8..0ee2a10a 100644 --- a/kernel-src/include/kernel/net.h +++ b/kernel-src/include/kernel/net.h @@ -29,6 +29,7 @@ typedef struct netdev_t { size_t mtu; uint32_t ip; hashtable_t arpcache; + bool doarp; int (*allocdesc)(size_t requestedsize, netdesc_t *desc); int (*sendpacket)(struct netdev_t *_internal, netdesc_t desc, mac_t targetmac, int proto); } netdev_t; @@ -76,6 +77,8 @@ void arp_init(); void ipv4_init(); void udp_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); int arp_lookup(netdev_t *netdev, uint32_t ip, mac_t *mac); diff --git a/kernel-src/io/net/ipv4.c b/kernel-src/io/net/ipv4.c index 8118df57..162fb251 100644 --- a/kernel-src/io/net/ipv4.c +++ b/kernel-src/io/net/ipv4.c @@ -168,9 +168,11 @@ int ipv4_sendpacket(void *buffer, size_t packetsize, uint32_t ip, int proto, net if (entry.netdev == NULL) return 0; // if a packet can't be routed to anywhere just pretend it was sent somewhere - int error = arp_lookup(entry.netdev, entry.gateway ? entry.gateway : ip, &mac); - if (error) - return error; + if (entry.netdev->doarp) { + int error = arp_lookup(entry.netdev, entry.gateway ? entry.gateway : ip, &mac); + if (error) + return error; + } netdev = entry.netdev; } else { @@ -207,4 +209,5 @@ void ipv4_init() { MUTEX_INIT(&routingtablelock); routingtable = alloc(sizeof(routingentry_t)); __assert(routingtable); + __assert(ipv4_addroute(loopback_device(), 0x7f000001, 0, 0xff000000, 10000) == 0); } diff --git a/kernel-src/io/net/loopback.c b/kernel-src/io/net/loopback.c new file mode 100644 index 00000000..228bc3c2 --- /dev/null +++ b/kernel-src/io/net/loopback.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static netdev_t loopbacknetdev; + +static void rx_dpc(context_t *context, dpcarg_t arg) { + eth_process(&loopbacknetdev, arg); +} + +// requested size doesn't account for ethernet header or the virtio header +static int loopback_allocdesc(size_t requestedsize, netdesc_t *desc) { + desc->address = alloc(requestedsize + sizeof(ethframe_t)); + if (desc->address == NULL) + return ENOMEM; + + desc->size = requestedsize + sizeof(ethframe_t); + desc->curroffset = sizeof(ethframe_t); + return 0; +} + +static int loopback_sendpacket(netdev_t *netdev, netdesc_t desc, mac_t targetmac, int proto) { + desc.curroffset = 0; + ethframe_t ethframe = { + .type = cpu_to_be_w(proto) + }; + + mac_t broadcast = NET_BROADCAST_MAC; + + memcpy(ðframe.source, &netdev->mac, sizeof(mac_t)); + memcpy(ðframe.destination, &broadcast, sizeof(mac_t)); + memcpy(desc.address, ðframe, sizeof(ethframe_t)); + + dpc_t dpc = {0}; + dpc_enqueue(&dpc, rx_dpc, desc.address); + + return 0; +} + +netdev_t *loopback_device() { + return &loopbacknetdev; +} + +void loopback_init() { + loopbacknetdev.mtu = 30000; + loopbacknetdev.sendpacket = loopback_sendpacket; + loopbacknetdev.allocdesc = loopback_allocdesc; + loopbacknetdev.ip = 0x7f000001; + loopbacknetdev.doarp = false; + __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/vionet.c b/kernel-src/io/net/vionet.c index 4bd24ebd..d294eab5 100644 --- a/kernel-src/io/net/vionet.c +++ b/kernel-src/io/net/vionet.c @@ -179,6 +179,7 @@ int vionet_newdevice(viodevice_t *viodevice) { netdev->netdev.mtu = 1500; netdev->netdev.sendpacket = vionet_sendpacket; netdev->netdev.allocdesc = vionet_allocdesc; + netdev->netdev.doarp = true; __assert(hashtable_init(&netdev->netdev.arpcache, 30) == 0); // initialize queues