VDE networking support

Adds VDE (https://github.com/virtualsquare/vde-2) support to 86Box.
- Adds new networking type
- Modifies networking configuration dialog
- Adds CMake Presets to build and debug under MacOS
This commit is contained in:
Jordi Guillaumes i Pons
2023-05-04 21:12:02 +02:00
parent ec51229fd5
commit 52b0e54fd7
9 changed files with 701 additions and 181 deletions

3
.gitignore vendored
View File

@@ -56,3 +56,6 @@ CMakeLists.txt.user
/debian/debhelper-build-stamp
/debian/files
/obj-*-linux-gnu
# MacOS Finder stuff
.DS_Store

View File

@@ -56,6 +56,72 @@
"NEW_DYNAREC": "ON"
},
"inherits": "base"
},
{
"name": "llvm-macos-aarch64.cmake",
"displayName": "MacOS clang regular",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake",
"NEW_DYNAREC": "ON",
"QT": "ON",
"USE_QT6": "OFF",
"Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5",
"MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk",
"Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools",
"OpenAL_ROOT": "/opt/homebrew/opt/openal-soft"
},
"inherits": "regular"
},
{
"name": "llvm-macos-aarch64-debug",
"displayName": "MacOS clang debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake",
"NEW_DYNAREC": "ON",
"QT": "ON",
"USE_QT6": "OFF",
"Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5",
"MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk",
"Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools",
"OpenAL_ROOT": "/opt/homebrew/opt/openal-soft",
"CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG",
"CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG"
},
"inherits": "debug"
},
{
"name": "flags-gcc-aarch64-debug",
"displayName": "Linux ARM 64 - Debug",
"description": "Linux ARM64 - Debug build",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"NEW_DYNAREC": "ON",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
"CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG",
"CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG"
},
"inherits": "debug"
},
{
"name": "flags-gcc-aarch64-regular",
"displayName": "Linux ARM 64 - Regular",
"description": "Linux ARM64 - Release build",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"NEW_DYNAREC": "ON",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
},
"inherits": "regular"
}
],
"buildPresets": [],

View File

@@ -783,6 +783,8 @@ load_network(void)
net_cards_conf[c].net_type = NET_TYPE_PCAP;
else if (!strcmp(p, "slirp") || !strcmp(p, "2"))
net_cards_conf[c].net_type = NET_TYPE_SLIRP;
else if (!strcmp(p, "vde") || !strcmp(p, "2"))
net_cards_conf[c].net_type = NET_TYPE_VDE;
else
net_cards_conf[c].net_type = NET_TYPE_NONE;
} else {
@@ -791,13 +793,17 @@ load_network(void)
p = ini_section_get_string(cat, "net_host_device", NULL);
if (p != NULL) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
} else if (network_dev_to_id(p) == -1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
if (net_cards_conf[c].net_type == NET_TYPE_PCAP) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
} else if (network_dev_to_id(p) == -1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
}
strcpy(net_cards_conf[c].host_dev_name, "none");
} else {
strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1);
}
strcpy(net_cards_conf[c].host_dev_name, "none");
} else {
strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1);
}
@@ -828,6 +834,8 @@ load_network(void)
net_cards_conf[c].net_type = NET_TYPE_PCAP;
} else if (!strcmp(p, "slirp") || !strcmp(p, "2")) {
net_cards_conf[c].net_type = NET_TYPE_SLIRP;
} else if (!strcmp(p, "vde") || !strcmp(p, "2")) {
net_cards_conf[c].net_type = NET_TYPE_VDE;
} else {
net_cards_conf[c].net_type = NET_TYPE_NONE;
}
@@ -838,13 +846,15 @@ load_network(void)
sprintf(temp, "net_%02i_host_device", c + 1);
p = ini_section_get_string(cat, temp, NULL);
if (p != NULL) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
} else if (network_dev_to_id(p) == -1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
if (net_cards_conf[c].net_type == NET_TYPE_PCAP) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
} else if (network_dev_to_id(p) == -1) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
}
strcpy(net_cards_conf[c].host_dev_name, "none");
}
strcpy(net_cards_conf[c].host_dev_name, "none");
} else {
strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1);
}
@@ -2469,11 +2479,19 @@ save_network(void)
}
sprintf(temp, "net_%02i_net_type", c + 1);
if (net_cards_conf[c].net_type == NET_TYPE_NONE) {
ini_section_delete_var(cat, temp);
} else {
ini_section_set_string(cat, temp,
(net_cards_conf[c].net_type == NET_TYPE_SLIRP) ? "slirp" : "pcap");
switch(net_cards_conf[c].net_type) {
case NET_TYPE_NONE:
ini_section_delete_var(cat, temp);
break;
case NET_TYPE_SLIRP:
ini_section_set_string(cat, temp, "slirp");
break;
case NET_TYPE_PCAP:
ini_section_set_string(cat, temp, "pcap");
break;
case NET_TYPE_VDE:
ini_section_set_string(cat, temp, "vde");
break;
}
sprintf(temp, "net_%02i_host_device", c + 1);

View File

@@ -51,6 +51,7 @@
#define NET_TYPE_NONE 0 /* networking disabled */
#define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */
#define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */
#define NET_TYPE_VDE 3 /* use the VDE plug API */
#define NET_MAX_FRAME 1518
/* Queue size must be a power of 2 */
@@ -123,6 +124,7 @@ typedef struct netdrv_t {
extern const netdrv_t net_pcap_drv;
extern const netdrv_t net_slirp_drv;
extern const netdrv_t net_vde_drv;
struct _netcard_t {
const device_t *device;
@@ -147,15 +149,27 @@ typedef struct {
char description[128];
} netdev_t;
typedef struct {
int has_slirp: 1;
int has_pcap: 1;
int has_vde: 1;
} network_devmap_t;
#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde)
#ifdef __cplusplus
extern "C" {
#endif
/* Global variables. */
extern int nic_do_log; /* config */
extern int network_ndev;
extern network_devmap_t network_devmap;
extern int network_ndev; // Number of pcap devices
extern network_devmap_t network_devmap; // Bitmap of available network types
extern netdev_t network_devs[NET_HOST_INTF_MAX];
/* Function prototypes. */
extern void network_init(void);
extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state);
@@ -166,6 +180,8 @@ extern int network_available(void);
extern void network_tx(netcard_t *card, uint8_t *, int);
extern int net_pcap_prepare(netdev_t *);
extern int net_vde_prepare(void);
extern void network_connect(int id, int connect);
extern int network_is_connected(int id);

View File

@@ -12,8 +12,8 @@
#
# Copyright 2020-2021 David Hrdlička.
#
add_library(net OBJECT network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c
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)
option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF)
@@ -39,3 +39,13 @@ endif()
if(WIN32)
target_link_libraries(86Box ws2_32)
endif()
if (UNIX)
find_path(HAS_VDE "libvdeplug.h" PATHS ${VDE_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" )
if(HAS_VDE)
add_compile_definitions(HAS_VDE)
list(APPEND net_sources net_vde.c)
endif()
endif()
add_library(net OBJECT ${net_sources})

310
src/network/net_vde.c Normal file
View File

@@ -0,0 +1,310 @@
/*
* 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.
*
* VDE networking for 86box
* See https://wiki.virtualsquare.org/#!tutorials/vdebasics.md
* for basic information about VDE. You can browse the source
* code at https://github.com/virtualsquare/vde-2
*
* VDE support is only available in Linux and MacOS. It _should_
* be available in BSD*, and if someday there is a BSD version of
* 86box this _could_ work out of the box.
*
* Authors: jguillaumes <jguillaumes@gmail.com>
* Copyright 2023 jguillaumes.
*
* See the COPYING file at the top of the 86box for license details.
* TL;DR: GPL version 2.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#if !defined(_WIN32)
#include <poll.h>
#include <unistd.h>
#else
#error VDE is not supported under windows
#endif
#include <libvdeplug.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/thread.h>
#include <86box/timer.h>
#include <86box/network.h>
#include <86box/net_event.h>
#define VDE_PKT_BATCH NET_QUEUE_LEN
#define VDE_DESCRIPTION "86Box virtual card"
enum {
NET_EVENT_STOP = 0,
NET_EVENT_TX,
NET_EVENT_RX,
NET_EVENT_VDE,
NET_EVENT_MAX
};
static volatile void *libvde_handle = NULL;
//+
// VDE connection structure
//-
typedef struct {
void *vdeconn; // VDEPLUG Connection
netcard_t *card; // NIC linked to
thread_t *poll_tid; // Polling thread
net_evt_t tx_event; // Packets to transmit event
net_evt_t stop_event; // Stop thread event
netpkt_t pkt; // Packet read/sent
netpkt_t pktv[VDE_PKT_BATCH]; // Packet queue
uint8_t mac_addr[6]; // MAC Address
} net_vde_t;
//+
// VDE libvdeplug function pointers
//-
static VDECONN *(*f_vde_open)(char *, char *, int, struct vde_open_args *); // This is vde_open_real()
static void (*f_vde_close)(VDECONN *);
static int (*f_vde_datafd)(VDECONN *); // Get the data (read/write) handle
static int (*f_vde_ctlfd)(VDECONN *); // Get the control handle
static ssize_t (*f_vde_recv)(VDECONN *, void *, size_t, int); // Receive a packet
static ssize_t (*f_vde_send)(VDECONN *, const void *, size_t, int); // Send a packet
//+
// VDE libvdeplug function table (for import)
//-
static dllimp_t vde_imports[] = {
{"vde_open_real", &f_vde_open},
{"vde_close", &f_vde_close},
{"vde_datafd", &f_vde_datafd},
{"vde_ctlfd", &f_vde_ctlfd},
{"vde_recv", &f_vde_recv},
{"vde_send", &f_vde_send},
{ NULL, NULL}
};
#ifdef ENABLE_VDE_LOG
#include <stdarg.h>
int vde_do_log = ENABLE_VDE_LOG;
static void
vde_log(const char *fmt, ...) {
va_list ap;
if (vde_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define vde_log(fmt, ...)
#endif
#ifdef _WIN32
#error VDE networking is not supported under windows
#else
//+
// VDE thread
//-
static void net_vde_thread(void *priv) {
net_vde_t *vde = (net_vde_t *) priv;
vde_log("VDE: Polling started.\n");
struct pollfd pfd[NET_EVENT_MAX];
pfd[NET_EVENT_STOP].fd = net_event_get_fd(&vde->stop_event);
pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI;
pfd[NET_EVENT_TX].fd = net_event_get_fd(&vde->tx_event);
pfd[NET_EVENT_TX].events = POLLIN | POLLPRI;
pfd[NET_EVENT_RX].fd = f_vde_datafd(vde->vdeconn);
pfd[NET_EVENT_RX].events = POLLIN;
pfd[NET_EVENT_VDE].fd = f_vde_ctlfd(vde->vdeconn);
pfd[NET_EVENT_VDE].events = POLLIN;
while(1) {
poll(pfd, NET_EVENT_MAX, -1);
// Acvity in the control handle means the link is closed
// We send ourselves a STOP event
if (pfd[NET_EVENT_VDE].revents & POLLIN) {
net_event_set(&vde->stop_event);
}
// There are packets queued to transmit
if (pfd[NET_EVENT_TX].revents & POLLIN) {
net_event_clear(&vde->tx_event);
int packets = network_tx_popv(vde->card, vde->pktv, VDE_PKT_BATCH);
for (int i=0; i<packets; i++) {
int nc = f_vde_send(vde->vdeconn, vde->pktv[i].data,vde->pktv[i].len, 0 );
if (nc == 0) {
vde_log("VDE: Problem, no bytes sent.\n");
}
}
}
// Packets are available for reading. Read packet and queue it
if (pfd[NET_EVENT_RX].revents & POLLIN) {
int nc = f_vde_recv(vde->vdeconn, vde->pkt.data, NET_MAX_FRAME, 0);
vde->pkt.len = nc;
network_rx_put_pkt(vde->card, &vde->pkt);
}
// We have been told to close
if (pfd[NET_EVENT_STOP].revents & POLLIN) {
net_event_clear(&vde->stop_event);
break;
}
}
vde_log("VDE: Polling stopped.\n");
}
#endif
//+
// Prepare the VDE libvdeplug interface.
// Load the dynamic library libvdeplug.
// Returns zero if the library has been loaded, -1 in case of error.
//-
int net_vde_prepare(void) {
#if defined(_WIN32)
#error VDE is not supported in Windows
#elif defined(__APPLE__)
libvde_handle = dynld_module("libvdeplug.dylib", vde_imports);
#else
libvde_handle = dynld_module("libvdeplug.so", vde_imports);
#endif
if (libvde_handle == NULL) {
vde_log("VDE: error loading VDEPLUG module\n");
return -1;
} else {
network_devmap.has_vde = 1;
}
return 0;
}
//+
// Close a VDE socket connection
//-
void net_vde_close(void *priv) {
int i;
if (!priv) return;
net_vde_t *vde = (net_vde_t *) priv;
vde_log("VDE: closing.\n");
net_event_set(&vde->stop_event); // Tell the thread to finish
vde_log("VDE: Waiting for the thread to finish...\n");
thread_wait(vde->poll_tid);
vde_log("VDE: Thread finished.\n");
// Free all the mallocs!
for(i=0;i<VDE_PKT_BATCH; i++) {
free(vde->pktv[i].data);
}
free(vde->pkt.data);
f_vde_close((void *) vde->vdeconn);
net_event_close(&vde->tx_event);
net_event_close(&vde->stop_event);
free(vde);
}
//+
// Signal packets are available to be transmitted
//-
void net_vde_in_available(void *priv) {
net_vde_t *vde = (net_vde_t *) priv;
net_event_set(&vde->tx_event);
}
//+
// Initialize VDE for use
// At this point the vdeplug library is already loaded
// card: network card we are attaching
// mac_addr: MAC address we are using
// priv: Name of the VDE contol socket directory
//-
void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv) {
struct vde_open_args vde_args;
int i;
char *socket_name = (char *) priv;
if (libvde_handle == NULL) {
vde_log("VDE: net_vde_init without library handle!\n");
return NULL;
}
if ((socket_name[0] == '\0') || !strcmp(socket_name, "none")) {
vde_log("VDE: No socket name configured!\n");
return NULL;
}
vde_log("VDE: Attaching to virtual switch at %s\n", socket_name);
net_vde_t *vde = calloc(1, sizeof(net_vde_t));
vde->card = (netcard_t *) card;
memcpy(vde->mac_addr, mac_addr, sizeof(vde->mac_addr));
vde_args.group = 0;
vde_args.port = 0;
vde_args.mode = 0;
// We are calling vde_open_real(), not the vde_open() macro...
if ((vde->vdeconn = f_vde_open(socket_name, VDE_DESCRIPTION,
LIBVDEPLUG_INTERFACE_VERSION, &vde_args)) == NULL) {
vde_log("VDE: Unable to open socket %s (%s)!\n", socket_name, strerror(errno));
free(vde);
//+
// There is a bug upstream that causes an uncontrolled crash if the network is not
// properly initialized.
// To avoid that crash, we tell the user we cannot continue and exit the program.
// 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);
// 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;
}
vde_log("VDE: Socket opened (%s).\n", socket_name);
for(i=0; i < VDE_PKT_BATCH; i++) {
vde->pktv[i].data = calloc(1, NET_MAX_FRAME);
}
vde->pkt.data = calloc(1,NET_MAX_FRAME);
net_event_init(&vde->tx_event);
net_event_init(&vde->stop_event);
vde->poll_tid = thread_create(net_vde_thread, vde); // Fire up the read-write thread!
return vde;
}
//+
// VDE Driver structure
//-
const netdrv_t net_vde_drv = {
&net_vde_in_available,
&net_vde_init,
&net_vde_close,
NULL
};

View File

@@ -123,7 +123,8 @@ netcard_conf_t net_cards_conf[NET_CARD_MAX];
uint16_t net_card_current = 0;
/* Global variables. */
int network_ndev;
network_devmap_t network_devmap;
int network_ndev;
netdev_t network_devs[NET_HOST_INTF_MAX];
/* Local variables. */
@@ -214,9 +215,20 @@ network_init(void)
network_ndev = 1;
/* Initialize the Pcap system module, if present. */
network_devmap.has_slirp = 1;
i = net_pcap_prepare(&network_devs[network_ndev]);
if (i > 0)
if (i > 0) {
network_devmap.has_pcap = 1;
network_ndev += i;
}
#ifdef HAS_VDE
// Try to load the VDE plug library
if(net_vde_prepare()==0) {
network_devmap.has_vde = 1;
}
#endif
#if defined ENABLE_NETWORK_LOG && !defined(_WIN32)
/* Start packet dump. */
@@ -286,6 +298,17 @@ int
network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt)
{
if (src_pkt->len == 0 || src_pkt->len > NET_MAX_FRAME || network_queue_full(queue)) {
#ifdef DEBUG
if (src_pkt->len == 0) {
network_log("Discarded zero length packet.\n");
} else if (src_pkt->len > NET_MAX_FRAME) {
network_log("Discarded oversized packet of len=%d.\n", src_pkt->len);
network_dump_packet(src_pkt);
} else {
network_log("Discarded %d bytes packet because the queue is full.\n", src_pkt->len);
network_dump_packet(src_pkt);
}
#endif
return 0;
}
@@ -434,6 +457,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin
card->host_drv = net_pcap_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
break;
#ifdef HAS_VDE
case NET_TYPE_VDE:
card->host_drv = net_vde_drv;
card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name);
break;
#endif
}
if (!card->host_drv.priv) {
@@ -617,6 +646,8 @@ network_dev_available(int id)
if ((net_cards_conf[id].net_type == NET_TYPE_PCAP && (network_dev_to_id(net_cards_conf[id].host_dev_name) <= 0)))
available = 0;
// TODO: Handle VDE device
return available;
}

View File

@@ -37,13 +37,17 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui)
auto *net_type_cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
auto *conf_btn = findChild<QPushButton *>(QString("pushButtonConf%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
int netType = net_type_cbox->currentData().toInt();
bool adaptersEnabled = netType == NET_TYPE_SLIRP || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0);
bool adaptersEnabled = netType == NET_TYPE_SLIRP
|| NET_TYPE_VDE
|| (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0);
intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP);
nic_cbox->setEnabled(adaptersEnabled);
conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt()));
socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE);
}
}
@@ -59,6 +63,7 @@ SettingsNetwork::SettingsNetwork(QWidget *parent)
auto *nic_cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1));
auto *net_type_cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
auto *intf_cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
connect(nic_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
connect(net_type_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
connect(intf_cbox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged);
@@ -75,12 +80,18 @@ SettingsNetwork::save()
{
for (int i = 0; i < NET_CARD_MAX; ++i) {
auto *cbox = findChild<QComboBox *>(QString("comboBoxNIC%1").arg(i + 1));
auto *socket_line = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i + 1));
net_cards_conf[i].device_num = cbox->currentData().toInt();
cbox = findChild<QComboBox *>(QString("comboBoxNet%1").arg(i + 1));
net_cards_conf[i].net_type = cbox->currentData().toInt();
cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name));
strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1);
if (net_cards_conf[i].net_type == NET_TYPE_PCAP) {
strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1);
} else if (net_cards_conf[i].net_type == NET_TYPE_VDE) {
const char *str_socket = socket_line->text().toStdString().c_str();
strncpy(net_cards_conf[i].host_dev_name, str_socket, strlen(str_socket));
}
}
}
@@ -124,26 +135,37 @@ SettingsNetwork::onCurrentMachineChanged(int machineId)
removeRows = model->rowCount();
Models::AddEntry(model, tr("None"), NET_TYPE_NONE);
Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP);
if (network_ndev > 1) {
Models::AddEntry(model, "PCap", NET_TYPE_PCAP);
}
if (network_devmap.has_vde) {
Models::AddEntry(model, "VDE", NET_TYPE_VDE);
}
model->removeRows(0, removeRows);
cbox->setCurrentIndex(net_cards_conf[i].net_type);
selectedRow = 0;
QString currentPcapDevice = net_cards_conf[i].host_dev_name;
cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
model = cbox->model();
removeRows = model->rowCount();
for (int c = 0; c < network_ndev; c++) {
Models::AddEntry(model, tr(network_devs[c].description), c);
if (QString(network_devs[c].device) == currentPcapDevice) {
selectedRow = c;
if (net_cards_conf[i].net_type == NET_TYPE_PCAP) {
QString currentPcapDevice = net_cards_conf[i].host_dev_name;
cbox = findChild<QComboBox *>(QString("comboBoxIntf%1").arg(i + 1));
model = cbox->model();
removeRows = model->rowCount();
for (int c = 0; c < network_ndev; c++) {
Models::AddEntry(model, tr(network_devs[c].description), c);
if (QString(network_devs[c].device) == currentPcapDevice) {
selectedRow = c;
}
}
model->removeRows(0, removeRows);
cbox->setCurrentIndex(selectedRow);
} else if (net_cards_conf[i].net_type == NET_TYPE_VDE) {
QString currentVdeSocket = net_cards_conf[i].host_dev_name;
auto editline = findChild<QLineEdit *>(QString("socketVDENIC%1").arg(i+1));
editline->setText(currentVdeSocket);
}
model->removeRows(0, removeRows);
cbox->setCurrentIndex(selectedRow);
}
}

View File

@@ -36,19 +36,6 @@
<string>Network Card #1</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxNIC1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
@@ -62,14 +49,17 @@
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet1">
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxNIC1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="2" column="2">
@@ -98,17 +88,14 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
@@ -121,7 +108,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -134,6 +121,33 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="socketVDENIC1">
<property name="maxLength">
<number>127</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>VDE Socket</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
@@ -141,6 +155,36 @@
<string>Network Card #2</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxIntf2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConf2">
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="sizePolicy">
@@ -154,19 +198,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
@@ -193,6 +224,19 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet2">
<property name="sizePolicy">
@@ -203,25 +247,28 @@
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxIntf2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConf2">
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Configure</string>
<string>VDE Socket</string>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="socketVDENIC2"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Network Card #3</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="socketVDENIC3"/>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@@ -233,23 +280,6 @@
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Network Card #3</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_13">
<property name="sizePolicy">
@@ -263,17 +293,14 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
<item row="1" column="0">
@@ -299,19 +326,6 @@
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConf3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxNIC3">
<property name="sizePolicy">
@@ -325,41 +339,8 @@
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Network Card #4</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxNIC4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConf4">
<widget class="QPushButton" name="pushButtonConf3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -371,14 +352,44 @@
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet4">
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>VDE Socket </string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mode</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Network Card #4</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="0">
<widget class="QLabel" name="label_16">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Adapter</string>
</property>
</widget>
</item>
<item row="1" column="0">
@@ -394,29 +405,6 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_16">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Adapter</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxIntf4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_14">
<property name="sizePolicy">
@@ -430,7 +418,43 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxNIC4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxNet4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonConf4">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Configure</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -443,6 +467,26 @@
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="comboBoxIntf4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="socketVDENIC4"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>VDE Socket</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>