#include #include #include #include #include #include #include #include #include static netdev_t loopbacknetdev; // requested size doesn't account for ethernet header or the virtio header 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; desc->size = requestedsize + sizeof(ethframe_t); desc->curroffset = sizeof(ethframe_t); 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 = { .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)); long ipl = interrupt_raiseipl(IPL_DPC); eth_process(netdev, desc.address, desc.size); interrupt_loweripl(ipl); 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() { __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(netdev_register(&loopbacknetdev, "lo") == 0); } INIT_ROUTINE_DEFINE(loopback, INIT_ROUTINE_FLAGS_NONE, loopback_init, devfs);