1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

ETHER: Add support for Omni OS and Open Indiana plus bridged network support

- Some versions of Omni OS no longer include sys/filio.h in sys/ioctl.h
- Add more robust support for locating OS tools in scp.c
- SHOW VERSION output displays SunOS host system specific info

Fix #1238
This commit is contained in:
Mark Pizzolato 2025-12-14 13:36:45 -10:00
parent fc460853ad
commit c31ea266e2
5 changed files with 120 additions and 14 deletions

View File

@ -51,7 +51,12 @@ Relatively recently, macOS (since version 10.15 sometime in 2019) has
functionality integrated into the OS that automatically provides bridging to
address this problem. The capability is provided by the vmnet facility of
the OS. The simh sim_ether layer now leverages this vmnet functionality
(when available), and building of simh on automatically includes it.
(when available), and building of simh on macOS automatically includes it.
In general, "attach xq eth0" will be useful to support this as well as
"attach xq eth1" will work using WiFi if it is connected to a network.
Relatively recently, SunOS (aka illumos) internally provides functionality
so that host<->simulator network traffic also simply works.
The following steps were performed to get a working SIMH vax simulator
sharing a physical NIC and allowing Host<->SIMH vax communications:

View File

@ -112,7 +112,7 @@ Simulator binaries for x86 Linus, x86 macOS, and Windows for all recent changes
- Enhanced Ethernet functionality on macOS which leverages the OS provided vmnet capabilities. This is available on all intel and Apple Silicon macOS systems starting with Catalina (10.15) which was released in 2019.
- SCP IF command supports RegEx comparisons.
- Windows builds are supported running all versions of Microsoft Visual Studio, including the most recent VS2026.
- All simulators build with full functionality on illumos Open Indiana.
- All simulators build with full functionality and extended/simplified network support on illumos Open Indiana and Omni OS.
#### All simulators build cleanly under OpenVMS on ia64 systems.

View File

@ -889,6 +889,9 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
ifneq (,$(call find_include,sys/ioctl))
OS_CCDEFS += -DHAVE_SYS_IOCTL
endif
ifneq (,$(and $(call find_include,sys/filio),$(shell grep FIONBIO $(call find_include,sys/filio))))
OS_CCDEFS += -DHAVE_SYS_FILIO
endif
ifneq (,$(call find_include,linux/cdrom))
OS_CCDEFS += -DHAVE_LINUX_CDROM
endif

57
scp.c
View File

@ -7080,6 +7080,7 @@ fprintf (st, "%s", sprint_capac (dptr, uptr));
const char *sim_get_tool_path (const char *tool)
{
char findcmd[PATH_MAX+1];
char notfound[PATH_MAX+1];
static char toolpath[PATH_MAX+1];
FILE *f;
@ -7103,6 +7104,9 @@ if ((f = popen (findcmd, "r"))) {
sim_trim_endspc (toolpath);
} while (toolpath[0] == '\0');
pclose (f);
snprintf (notfound, sizeof (notfound), "%s not found", tool);
if (strcmp (notfound, toolpath) == 0)
toolpath[0] = '\0';
}
if (toolpath[0] == '\0') { /* Not found yet? */
#if defined(FIND_CMD_EXTRA) /* Try with alternative command */
@ -7114,6 +7118,12 @@ if (toolpath[0] == '\0') { /* Not found yet? */
sim_trim_endspc (toolpath);
} while (toolpath[0] == '\0');
pclose (f);
snprintf (notfound, sizeof (notfound), "%s not found", tool);
if (strcmp (notfound, toolpath) == 0)
toolpath[0] = '\0';
snprintf (notfound, sizeof (notfound), "no %s in ", tool);
if (strstr (toolpath, notfound) != NULL)
toolpath[0] = '\0';
}
#endif
}
@ -7551,6 +7561,53 @@ if (1) {
setenv ("SIM_HOST_MAX_THREADS", procs, 1);
}
}
#elif defined (__illumos__)
if ((f = popen ("psrinfo -p -v 2>/dev/null", "r"))) {
char line[256];
int n1, n2;
int cores = 0;
int procs = 0;
char proc_name[PATH_MAX+1] = "";
char *c;
do {
if (NULL == fgets (line, sizeof (line), f))
break;
sim_trim_endspc (line);
if (2 == sscanf (line, "The physical processor has %d cores and %d virtual processors", &n1, &n2)) {
cores = n1;
procs = n2;
continue;
}
if (1 == sscanf (line, "The physical processor has %d virtual processors", &n1)) {
procs = n1;
continue;
}
if ((memcmp (line, " ", 6) == 0) ||
(line[0] == '\t')) {
if ((c = strchr (line, '['))) {
*c = '\0';
sim_trim_spc (line);
}
strlcpy (proc_name, line, sizeof (proc_name));
}
} while ((proc_name[0] == '\0') || (cores == 0) || (procs == 0));
pclose (f);
if (proc_name[0] != '\0')
fprintf (st, "\n Processor Name: %s", proc_name);
if ((procs != 0) || (cores != 0))
fprintf (st, "\n ");
if (cores != 0) {
snprintf (line, sizeof (line), "%d", cores);
fprintf (st, "Cores: %s", line);
setenv ("SIM_HOST_CORE_COUNT", line, 1);
}
if (procs != 0) {
snprintf (line, sizeof (line), "%d", procs);
fprintf (st, "%sLogical Processors: %s", (cores != 0) ? ", " : "", line);
setenv ("SIM_HOST_MAX_THREADS", line, 1);
}
}
#endif
strlcpy (tarversion, _get_tool_version ("tar"), sizeof (tarversion));
if (tarversion[0]) {

View File

@ -1126,8 +1126,11 @@ t_stat sim_ether_test (DEVICE *dptr, const char *cptr)
#else /* endif unimplemented */
#if (defined (xBSD) || defined (__APPLE__)) && (defined (HAVE_TAP_NETWORK) || defined (HAVE_PCAP_NETWORK))
#if (defined (xBSD) || defined (__APPLE__) || defined (__illumos__)) && (defined (HAVE_TAP_NETWORK) || defined (HAVE_PCAP_NETWORK))
#include <sys/ioctl.h>
#if (!defined (FIONBIO)) && defined (HAVE_SYS_FILIO)
#include <sys/filio.h>
#endif
#include <net/bpf.h>
#endif
@ -1453,6 +1456,7 @@ else {
/* copy device list into the passed structure */
for (used=0, dev=alldevs; dev && (used < max); dev=dev->next) {
char Info[ETH_DEV_INFO_MAX];
static const ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
edev.eth_api = ETH_API_PCAP;
eth_get_nic_hw_addr (&edev, dev->name, 0, Info);
@ -1460,11 +1464,17 @@ else {
continue;
if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name)))
continue;
if (memcmp (edev.host_nic_phy_hw_addr, zeros, sizeof (ETH_MAC)) == 0)
continue;
strlcpy(list[used].name, dev->name, sizeof(list[used].name));
if (dev->description)
strlcpy(list[used].desc, dev->description, sizeof(list[used].desc));
else {
#if defined (__illumos__)
strlcpy(list[used].desc, "Bridged Ethernet support", sizeof(list[used].desc));
#else
strlcpy(list[used].desc, "No description available", sizeof(list[used].desc));
#endif
if (Info[0] != '\0')
snprintf(list[used].info, sizeof(list[used].info), "%s", Info);
}
@ -2124,11 +2134,12 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on, c
FILE *f;
int i;
char tool[CBUFSIZE];
const char *turnon[] = {
static const ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
static const char *turnon[] = {
"ip link set dev %.*s up 2>/dev/null",
"ifconfig %.*s up 2>/dev/null",
NULL};
const char *MACpatterns[] = {
static const char *MACpatterns[] = {
"ip link show %.*s 2>/dev/null | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F] 2>/dev/null",
"ip link show %.*s 2>/dev/null | grep -E [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F] 2>/dev/null",
"ip link show %.*s 2>/dev/null | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F] 2>/dev/null",
@ -2136,7 +2147,7 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on, c
"ifconfig %.*s 2>/dev/null | grep -E [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F] 2>/dev/null",
"ifconfig %.*s 2>/dev/null | egrep [0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F]:[0-9a-fA-F]?[0-9a-fA-F] 2>/dev/null",
NULL};
const char *IPv4patterns[] = {
static const char *IPv4patterns[] = {
"ip -4 address show %.*s 2>/dev/null | grep 'inet ' 2>/dev/null",
"ip -4 address show %.*s 2>/dev/null | grep -E 'inet ' 2>/dev/null",
"ip -4 address show %.*s 2>/dev/null | egrep 'inet ' 2>/dev/null",
@ -2144,15 +2155,15 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on, c
"ifconfig %.*s 2>/dev/null | grep -E 'inet ' 2>/dev/null",
"ifconfig %.*s 2>/dev/null | egrep 'inet ' 2>/dev/null",
NULL};
const char *LinkTypepatterns[] = {
static const char *LinkTypepatterns[] = {
"ipconfig getsummary %.*s 2>/dev/null | grep 'InterfaceType' 2>/dev/null | awk '{ print $3 }'",
"nmcli device 2>/dev/null | grep %.*s 2>/dev/null | grep 'Wired connection' 2>/dev/null | awk '{ print $2 }'",
"nmcli device 2>/dev/null | grep %.*s 2>/dev/null | grep -e 'wifi' -e 'ethernet' 2>/dev/null | awk '{ print $2 }'",
NULL};
const char *LinkStatuspatterns[] = {
static const char *LinkStatuspatterns[] = {
"ifconfig %.*s 2>/dev/null | grep 'status: ' 2>/dev/null | awk '{if ($0 ~ /status: inactive/) { print \"MediaState: disconnected\" } else {if ($0 ~ /status: active/) { print \"MediaState: connected\" }}}'",
NULL};
const char *LinkStatusDownpatterns[] = {
static const char *LinkStatusDownpatterns[] = {
"ip -4 link show %.*s 2>/dev/null | grep 'NO-CARRIER' 2>/dev/null | grep 'state DOWN' 2>/dev/null",
NULL};
@ -2225,14 +2236,16 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on, c
unsigned int byt1, byt2, byt3, byt4;
int j;
char *p2 = strstr(p1, "netmask");
int netmask = 0xFFFFFFFF;
uint32 netmask = 0xFFFFFFFF;
char cidr[4];
if (NULL != p2) {
if (4 == sscanf(p2, "netmask %u.%u.%u.%u", &byt1, &byt2, &byt3, &byt4))
netmask = (byt1 << 24) | (byt2 << 16) | (byt3 << 8) | byt4;
else
sscanf(p2, "netmask 0x%x", &netmask);
else {
if (1 != sscanf(p2, "netmask 0x%x", &netmask))
sscanf(p2, "netmask %x", &netmask);
}
if (netmask != 0xFFFFFFFF) {
for (j = 0; j < 32; j++)
if (0 == (netmask & (1 << (31 - j)))) {
@ -2383,8 +2396,36 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on, c
}
}
}
}
#if defined (__illumos__)
if (memcmp (dev->host_nic_phy_hw_addr, zeros, sizeof (ETH_MAC)) != 0) {
t_bool promisc_mode = FALSE;
snprintf(command, sizeof(command), "ifconfig %s 2>/dev/null", devname);
get_glyph_nc (command, tool, 0);
if (sim_get_tool_path (tool)[0]) {
if (NULL != (f = popen(command, "r"))) {
while (fgets(result, sizeof(result), f) != NULL) {
if (strstr (result, "PROMISC") != NULL) {
promisc_mode = TRUE;
break;
}
}
pclose(f);
}
if (promisc_mode == FALSE) {
snprintf(command, sizeof(command), "dladm create-vnic -l %s vnic99; dladm set-linkprop -p promisc-filtered=off vnic0 2>/dev/null", devname);
get_glyph_nc (command, tool, 0);
if (sim_get_tool_path (tool)[0]) {
if (NULL != (f = popen(command, "r"))) {
while (fgets(result, sizeof(result), f) != NULL);
pclose(f);
}
}
}
}
}
#endif
}
#endif
}
@ -5234,7 +5275,7 @@ if (dev->error_reopen_count)
fprintf(st, " Error Reopen Count: %d\n", (int)dev->error_reopen_count);
if (1) {
int i, count = 0;
ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
static const ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
char buffer[20];
for (i = 0; i < ETH_FILTER_MAX; i++) {