2022-06-27 19:36:56 +02:00
|
|
|
/*
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
UMKa - User-Mode KolibriOS developer tools
|
|
|
|
vnet - virtual network card
|
|
|
|
|
2023-02-01 19:30:44 +01:00
|
|
|
Copyright (C) 2020-2023 Ivan Baravy <dunkaist@gmail.com>
|
2022-06-27 19:36:56 +02:00
|
|
|
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
|
|
|
|
*/
|
|
|
|
|
2022-06-27 14:32:29 +02:00
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <inttypes.h>
|
2023-02-01 19:30:44 +01:00
|
|
|
#define _POSIX // to have SIGSYS on windows
|
|
|
|
#include <signal.h>
|
2023-02-02 01:37:11 +01:00
|
|
|
#include <stdatomic.h>
|
2020-05-06 23:33:32 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2020-05-07 03:57:01 +02:00
|
|
|
#include "umka.h"
|
2020-05-06 23:33:32 +02:00
|
|
|
#include "trace.h"
|
2020-10-14 05:30:01 +02:00
|
|
|
#include "vnet.h"
|
2023-02-01 19:30:44 +01:00
|
|
|
#include "vnet/tap.h"
|
|
|
|
#include "vnet/file.h"
|
2020-10-10 01:30:52 +02:00
|
|
|
|
2021-12-12 11:35:35 +01:00
|
|
|
// TODO: Cleanup
|
|
|
|
#ifndef _WIN32
|
2023-02-01 19:30:44 +01:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <poll.h>
|
2021-12-12 11:35:35 +01:00
|
|
|
#include <unistd.h>
|
2023-02-01 19:30:44 +01:00
|
|
|
#else
|
|
|
|
#include <winsock2.h>
|
|
|
|
#include <pthread.h>
|
2021-12-12 11:35:35 +01:00
|
|
|
#endif
|
|
|
|
|
2022-06-27 14:32:29 +02:00
|
|
|
#define STACK_SIZE 0x10000
|
|
|
|
|
|
|
|
static int
|
|
|
|
vnet_input(void *udata) {
|
|
|
|
umka_sti();
|
2023-02-02 01:37:11 +01:00
|
|
|
struct vnet *vnet = udata;
|
|
|
|
int fd = vnet->fdin;
|
2022-06-27 14:32:29 +02:00
|
|
|
int plen = 0;
|
2022-06-28 10:23:14 +02:00
|
|
|
fprintf(stderr, "[vnet] input interrupt\n");
|
|
|
|
net_buff_t *buf = kos_net_buff_alloc(NET_BUFFER_SIZE);
|
|
|
|
if (!buf) {
|
|
|
|
fprintf(stderr, "[vnet] Can't allocate network buffer!\n");
|
|
|
|
return 1;
|
2022-06-27 14:32:29 +02:00
|
|
|
}
|
2023-02-02 01:37:11 +01:00
|
|
|
buf->device = &vnet->eth.net;
|
2023-02-01 19:30:44 +01:00
|
|
|
plen = read(fd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data));
|
2022-06-28 10:23:14 +02:00
|
|
|
if (plen == -1) {
|
|
|
|
plen = 0; // we have just allocated a buffer, so we have to submit it
|
|
|
|
}
|
2023-02-02 17:25:20 +01:00
|
|
|
|
2022-06-28 10:23:14 +02:00
|
|
|
fprintf(stderr, "[vnet] read %i bytes\n", plen);
|
|
|
|
for (int i = 0; i < plen; i++) {
|
|
|
|
fprintf(stderr, " %2.2x", buf->data[i]);
|
|
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
buf->length = plen;
|
|
|
|
buf->offset = offsetof(net_buff_t, data);
|
|
|
|
kos_eth_input(buf);
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet->input_processed = 1;
|
2022-06-27 14:32:29 +02:00
|
|
|
|
2022-06-28 10:23:14 +02:00
|
|
|
return 1; // acknowledge our interrupt
|
2020-05-06 23:33:32 +02:00
|
|
|
}
|
|
|
|
|
2022-06-27 14:32:29 +02:00
|
|
|
static void
|
2023-02-01 19:30:44 +01:00
|
|
|
vnet_input_monitor(struct vnet *net) {
|
2022-06-27 14:32:29 +02:00
|
|
|
umka_sti();
|
2023-02-01 19:30:44 +01:00
|
|
|
struct pollfd pfd = {net->fdin, POLLIN, 0};
|
|
|
|
while (1) {
|
|
|
|
if (net->input_processed && poll(&pfd, 1, 0)) {
|
|
|
|
net->input_processed = 0;
|
2023-02-02 01:37:11 +01:00
|
|
|
atomic_store_explicit(&umka_irq_number, UMKA_IRQ_NETWORK,
|
|
|
|
memory_order_release);
|
|
|
|
raise(UMKA_SIGNAL_IRQ);
|
2022-06-27 14:32:29 +02:00
|
|
|
umka_sti();
|
|
|
|
}
|
|
|
|
}
|
2020-05-06 23:33:32 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 19:30:44 +01:00
|
|
|
struct vnet *
|
|
|
|
vnet_init(enum vnet_type type) {
|
2023-02-02 01:37:11 +01:00
|
|
|
struct vnet *vnet;
|
2023-02-01 19:30:44 +01:00
|
|
|
switch (type) {
|
|
|
|
case VNET_FILE:
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet = vnet_init_file();
|
2023-02-01 19:30:44 +01:00
|
|
|
break;
|
|
|
|
case VNET_TAP:
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet = vnet_init_tap();
|
2023-02-01 19:30:44 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "[vnet] bad vnet type: %d\n", type);
|
|
|
|
return NULL;
|
|
|
|
}
|
2023-02-02 01:37:11 +01:00
|
|
|
if (!vnet) {
|
2023-02-01 19:30:44 +01:00
|
|
|
fprintf(stderr, "[vnet] device initialization failed\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2022-06-27 14:32:29 +02:00
|
|
|
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet->eth.net.link_state = ETH_LINK_FD + ETH_LINK_10M;
|
|
|
|
vnet->eth.net.hwacc = 0;
|
2022-06-27 14:32:29 +02:00
|
|
|
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet->eth.net.bytes_tx = 0;
|
|
|
|
vnet->eth.net.bytes_rx = 0;
|
2022-06-27 14:32:29 +02:00
|
|
|
|
2023-02-02 01:37:11 +01:00
|
|
|
vnet->eth.net.packets_tx = 0;
|
|
|
|
vnet->eth.net.packets_tx_err = 0;
|
|
|
|
vnet->eth.net.packets_tx_drop = 0;
|
|
|
|
vnet->eth.net.packets_tx_ovr = 0;
|
|
|
|
|
|
|
|
vnet->eth.net.packets_rx = 0;
|
|
|
|
vnet->eth.net.packets_rx_err = 0;
|
|
|
|
vnet->eth.net.packets_rx_drop = 0;
|
|
|
|
vnet->eth.net.packets_rx_ovr = 0;
|
|
|
|
|
|
|
|
kos_attach_int_handler(UMKA_IRQ_NETWORK, vnet_input, vnet);
|
2022-06-28 10:23:14 +02:00
|
|
|
fprintf(stderr, "[vnet] start input_monitor thread\n");
|
2022-06-27 14:32:29 +02:00
|
|
|
uint8_t *stack = malloc(STACK_SIZE);
|
|
|
|
size_t tid = umka_new_sys_threads(0, vnet_input_monitor, stack + STACK_SIZE);
|
|
|
|
appdata_t *t = kos_slot_base + tid;
|
2023-02-02 01:37:11 +01:00
|
|
|
*(void**)((uint8_t*)t->saved_esp0-12) = vnet; // param for monitor thread
|
2022-06-28 10:23:14 +02:00
|
|
|
// -12 here because in UMKa, unlike real hardware, we don't switch between
|
|
|
|
// kernel and userspace, i.e. stack structure is different
|
2022-06-27 14:32:29 +02:00
|
|
|
|
2023-02-02 01:37:11 +01:00
|
|
|
return vnet;
|
2020-10-14 19:56:28 +02:00
|
|
|
}
|