Finish merge.

This commit is contained in:
OBattler
2023-05-16 00:53:59 +02:00
parent 7343b7972c
commit 6bb5942ad1
14 changed files with 429 additions and 69 deletions

View File

@@ -14,7 +14,7 @@
#
set(net_sources)
list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c
net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c)
net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c)
option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF)
mark_as_advanced(SLIRP_EXTERNAL)

224
src/network/net_null.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Null network driver
*
*
*
* Authors: cold-brewed
*
* Copyright 2023 The 86Box development team
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <stdbool.h>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <winsock2.h>
#else
# include <poll.h>
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/network.h>
#include <86box/net_event.h>
enum {
NET_EVENT_STOP = 0,
NET_EVENT_TX,
NET_EVENT_RX,
NET_EVENT_MAX
};
/* Special define for the windows portion. Because we are not interested
* in NET_EVENT_RX for the null driver, we only need to poll up to
* NET_EVENT_TX. NET_EVENT_RX gives us a different NET_EVENT_MAX
* excluding NET_EVENT_RX. */
#define NET_EVENT_TX_MAX NET_EVENT_RX
#define NULL_PKT_BATCH NET_QUEUE_LEN
typedef struct {
uint8_t mac_addr[6];
netcard_t *card;
thread_t *poll_tid;
net_evt_t tx_event;
net_evt_t stop_event;
netpkt_t pkt;
netpkt_t pktv[NULL_PKT_BATCH];
} net_null_t;
#ifdef ENABLE_NET_NULL_LOG
int net_null_do_log = ENABLE_NET_NULL_LOG;
static void
net_null_log(const char *fmt, ...)
{
va_list ap;
if (net_null_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define net_null_log(fmt, ...)
#endif
#ifdef _WIN32
static void
net_null_thread(void *priv)
{
net_null_t *net_null = (net_null_t *) priv;
net_null_log("Null Network: polling started.\n");
HANDLE events[NET_EVENT_TX_MAX];
events[NET_EVENT_STOP] = net_event_get_handle(&net_null->stop_event);
events[NET_EVENT_TX] = net_event_get_handle(&net_null->tx_event);
bool run = true;
while (run) {
int ret = WaitForMultipleObjects(NET_EVENT_TX_MAX, events, FALSE, INFINITE);
switch (ret - WAIT_OBJECT_0) {
case NET_EVENT_STOP:
net_event_clear(&net_null->stop_event);
run = false;
break;
case NET_EVENT_TX:
net_event_clear(&net_null->tx_event);
int packets = network_tx_popv(net_null->card, net_null->pktv, NULL_PKT_BATCH);
for (int i = 0; i < packets; i++) {
net_null_log("Null Network: Ignoring TX packet (%d bytes)\n", net_null->pktv[i].len);
}
break;
default:
net_null_log("Null Network: Unknown event.\n");
break;
}
}
net_null_log("Null Network: polling stopped.\n");
}
#else
static void
net_null_thread(void *priv)
{
net_null_t *net_null = (net_null_t *) priv;
net_null_log("Null Network: polling started.\n");
struct pollfd pfd[NET_EVENT_MAX];
pfd[NET_EVENT_STOP].fd = net_event_get_fd(&net_null->stop_event);
pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TX].fd = net_event_get_fd(&net_null->tx_event);
pfd[NET_EVENT_TX].events = POLLIN | POLLPRI;
while (1) {
poll(pfd, NET_EVENT_MAX, -1);
if (pfd[NET_EVENT_STOP].revents & POLLIN) {
net_event_clear(&net_null->stop_event);
break;
}
if (pfd[NET_EVENT_TX].revents & POLLIN) {
net_event_clear(&net_null->tx_event);
int packets = network_tx_popv(net_null->card, net_null->pktv, NULL_PKT_BATCH);
for (int i = 0; i < packets; i++) {
net_null_log("Null Network: Ignoring TX packet (%d bytes)\n", net_null->pktv[i].len);
}
}
}
net_null_log("Null Network: polling stopped.\n");
}
#endif
void *
net_null_init(const netcard_t *card, const uint8_t *mac_addr, void *priv)
{
net_null_log("Null Network: Init\n");
net_null_t *net_null = calloc(1, sizeof(net_null_t));
net_null->card = (netcard_t *) card;
memcpy(net_null->mac_addr, mac_addr, sizeof(net_null->mac_addr));
for (int i = 0; i < NULL_PKT_BATCH; i++) {
net_null->pktv[i].data = calloc(1, NET_MAX_FRAME);
}
net_null->pkt.data = calloc(1, NET_MAX_FRAME);
net_event_init(&net_null->tx_event);
net_event_init(&net_null->stop_event);
net_null->poll_tid = thread_create(net_null_thread, net_null);
return net_null;
}
void
net_null_in_available(void *priv)
{
net_null_t *net_null = (net_null_t *) priv;
net_event_set(&net_null->tx_event);
}
void
net_null_close(void *priv)
{
if (!priv)
return;
net_null_t *net_null = (net_null_t *) priv;
net_null_log("Null Network: closing.\n");
/* Tell the thread to terminate. */
net_event_set(&net_null->stop_event);
/* Wait for the thread to finish. */
net_null_log("Null Network: waiting for thread to end...\n");
thread_wait(net_null->poll_tid);
net_null_log("Null Network: thread ended\n");
for (int i = 0; i < NULL_PKT_BATCH; i++) {
free(net_null->pktv[i].data);
}
free(net_null->pkt.data);
net_event_close(&net_null->tx_event);
net_event_close(&net_null->stop_event);
free(net_null);
}
const netdrv_t net_null_drv = {
&net_null_in_available,
&net_null_init,
&net_null_close,
NULL
};

View File

@@ -280,7 +280,7 @@ void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv) {
// TODO: Once there is a solution for the mentioned crash, this should be removed
// and/or replaced by proper error handling code.
//-
fatal("Could not open the specified VDE socket (%s). Please fix your networking configuration.", socket_name);
// fatal("Could not open the specified VDE socket (%s). Please fix your networking configuration.", socket_name);
// It makes no sense to issue this warning since the program will crash anyway...
// ui_msgbox_header(MBX_WARNING, (wchar_t *) IDS_2167, (wchar_t *) IDS_2168);
return NULL;

View File

@@ -123,7 +123,7 @@ netcard_conf_t net_cards_conf[NET_CARD_MAX];
uint16_t net_card_current = 0;
/* Global variables. */
network_devmap_t network_devmap;
network_devmap_t network_devmap = {0};
int network_ndev;
netdev_t network_devs[NET_HOST_INTF_MAX];
@@ -442,13 +442,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
card->card_num = net_card_current;
card->byte_period = NET_PERIOD_10M;
for (int i = 0; i < 3; i++) {
for (int i = 0; i < NET_QUEUE_COUNT; i++) {
network_queue_init(&card->queues[i]);
}
switch (net_cards_conf[net_card_current].net_type) {
case NET_TYPE_SLIRP:
default:
card->host_drv = net_slirp_drv;
card->host_drv.priv = card->host_drv.init(card, mac, NULL);
break;
@@ -463,18 +462,45 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
break;
#endif
default:
card->host_drv.priv = NULL;
break;
}
// Use null driver on:
// * No specific driver selected (card->host_drv.priv is set to null above)
// * Failure to init a specific driver (in which case card->host_drv.priv is null)
if (!card->host_drv.priv) {
thread_close_mutex(card->tx_mutex);
thread_close_mutex(card->rx_mutex);
for (int i = 0; i < 3; i++) {
network_queue_clear(&card->queues[i]);
if(net_cards_conf[net_card_current].net_type != NET_TYPE_NONE) {
// We're here because of a failure
// Placeholder to display a msgbox about falling back to null
ui_msgbox(MBX_ERROR | MBX_ANSI, "Network driver initialization failed. Falling back to NULL driver.");
}
// Init null driver
card->host_drv = net_null_drv;
card->host_drv.priv = card->host_drv.init(card, mac, NULL);
// Set link state to disconnected by default
network_connect(card->card_num, 0);
ui_sb_update_icon_state(SB_NETWORK | card->card_num, 1);
// If null fails, something is very wrong
// Clean up and fatal
if(!card->host_drv.priv) {
thread_close_mutex(card->tx_mutex);
thread_close_mutex(card->rx_mutex);
for (int i = 0; i < NET_QUEUE_COUNT; i++) {
network_queue_clear(&card->queues[i]);
}
free(card->queued_pkt.data);
free(card);
// Placeholder - insert the error message
fatal("Error initializing the network device: Null driver initialization failed");
return NULL;
}
free(card->queued_pkt.data);
free(card);
return NULL;
}
timer_add(&card->timer, network_rx_queue, card, 0);
@@ -491,7 +517,7 @@ netcard_close(netcard_t *card)
thread_close_mutex(card->tx_mutex);
thread_close_mutex(card->rx_mutex);
for (int i = 0; i < 3; i++) {
for (int i = 0; i < NET_QUEUE_COUNT; i++) {
network_queue_clear(&card->queues[i]);
}
@@ -641,7 +667,7 @@ network_dev_to_id(char *devname)
int
network_dev_available(int id)
{
int available = (net_cards_conf[id].device_num > 0) && (net_cards_conf[id].net_type != NET_TYPE_NONE);
int available = (net_cards_conf[id].device_num > 0);
if ((net_cards_conf[id].net_type == NET_TYPE_PCAP && (network_dev_to_id(net_cards_conf[id].host_dev_name) <= 0)))
available = 0;