[GXemul-devel] [PATCH] MAC address for emulated hosts
Status: Alpha
Brought to you by:
gavare
|
From: Jan-Benedict G. <jb...@lu...> - 2023-03-28 08:20:19
|
Hi!
On Mon, 2023-03-27 22:49:31 +0200, Jan-Benedict Glaw <jb...@lu...> wrote:
> On Sat, 2023-03-25 20:39:37 +0100, Jan-Benedict Glaw <jb...@lu...> wrote:
> > @Anders: Do you already have private patches to allow for
> > configurable MAC addresses? Or maybe I'd cook up something?
>
> I had a closer look. One quite simple way to have configurable MAC
> addresses could be to add a command line option (as well as a "mac()"
> option in the config file) to supply a list of comma-separated MAC
> addresses to be stored in struct machine.
>
> A helper function could be used to to parse that string and return
> (if available) the n'th MAC address (or an error.) This could be
> called by net_generate_unique_mac() to either pick a configured MAC
> address or place one (as before.)
>
> @Anders: Would you accept a patch like that? Or have a different idea
> for supplying / parsing MAC addresses?
No docs yet, but use it either with
`-l 10:11:12:13:14:15,10:12:14:16:18:20` on the command line or with
`mac_list("10:11:12:13:14:15")` within a `machine(...)` context inside
the config file. No docs yet. Works for me as far as tested (with just
one NIC on a simulated DECstation, so supplying multiple MAC addresses
wasn't actually tested yet.)
diff --git a/src/core/emul_parse.c b/src/core/emul_parse.c
index a16d80b..6e31465 100644
--- a/src/core/emul_parse.c
+++ b/src/core/emul_parse.c
@@ -224,6 +224,8 @@ static char cur_machine_start_paused[10];
static char cur_machine_ncpus[10];
static char cur_machine_n_gfx_cards[10];
static char cur_machine_serial_nr[10];
+#define MAX_MAC_LIST_LEN (8*20)
+static char cur_machine_mac_list[MAX_MAC_LIST_LEN];
static char cur_machine_emulated_hz[10];
static char cur_machine_memory[10];
#define MAX_N_LOAD 15
@@ -357,6 +359,7 @@ static void parse__emul(struct emul *e, FILE *f, int *in_emul, int *line,
cur_machine_serial_nr[0] = '\0';
cur_machine_emulated_hz[0] = '\0';
cur_machine_memory[0] = '\0';
+ cur_machine_mac_list[0] = '\0';
return;
}
@@ -528,6 +531,10 @@ static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
e->next_serial_nr = m->serial_nr+1;
}
+ if (cur_machine_mac_list[0]) {
+ m->mac_list = strdup (cur_machine_mac_list);
+ }
+
if (cur_machine_emulated_hz[0]) {
m->emulated_hz = mystrtoull(cur_machine_emulated_hz,
NULL, 0);
@@ -617,6 +624,7 @@ static void parse__machine(struct emul *e, FILE *f, int *in_emul, int *line,
WORD("force_netboot", cur_machine_force_netboot);
WORD("ncpus", cur_machine_ncpus);
WORD("serial_nr", cur_machine_serial_nr);
+ WORD("mac_list", cur_machine_mac_list);
WORD("n_gfx_cards", cur_machine_n_gfx_cards);
WORD("emulated_hz", cur_machine_emulated_hz);
WORD("memory", cur_machine_memory);
diff --git a/src/include/machine.h b/src/include/machine.h
index 02ee1f7..67b314b 100644
--- a/src/include/machine.h
+++ b/src/include/machine.h
@@ -119,6 +119,7 @@ struct machine {
is useful when emulating multiple cards in one machine: */
int serial_nr;
int nr_of_nics;
+ char *mac_list;
/* Main memory: */
struct memory *memory;
diff --git a/src/net/net_misc.c b/src/net/net_misc.c
index f2826b8..fd96559 100644
--- a/src/net/net_misc.c
+++ b/src/net/net_misc.c
@@ -76,6 +76,48 @@ void net_debugaddr(void *addr, int type)
}
+static int net_get_configured_mac(struct machine *m, unsigned int n, unsigned char *macbuf)
+{
+ char *start;
+ unsigned int mac[6];
+
+ fprintf (stderr, "Trying to find MAC address %u from \"%s\"\n", n, m->mac_list);
+
+ if (m == NULL || m->mac_list == NULL || macbuf == NULL)
+ return -1;
+
+ /* Find n'th MAC address. */
+ start = m->mac_list;
+ while (*start != '\0' && n > 0) {
+ if (*start == ',') {
+ n--;
+ }
+ start++;
+ }
+
+ /* Reached end-of-string. */
+ if (*start == '\0' || n > 0)
+ return -1;
+
+ /* Try to parse MAC address, copy to output buffer. */
+ fprintf (stderr, "MAC starts with %s\n", start);
+ if (sscanf(start, "%x:%x:%x:%x:%x:%x",
+ &mac[0], &mac[1], &mac[2],
+ &mac[3], &mac[4], &mac[5]) == 6) {
+
+ macbuf[0] = mac[0];
+ macbuf[1] = mac[1];
+ macbuf[2] = mac[2];
+ macbuf[3] = mac[3];
+ macbuf[4] = mac[4];
+ macbuf[5] = mac[5];
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
/*
* net_generate_unique_mac():
*
@@ -92,19 +134,23 @@ void net_generate_unique_mac(struct machine *machine, unsigned char *macbuf)
return;
}
- // Special case: real SGI machines have 0x08 as their first
- // byte, so let's mimic that.
- macbuf[0] = machine->machine_type == MACHINE_SGI ? 0x08 : 0x10;
- macbuf[1] = 0x20;
- macbuf[2] = 0x30;
- macbuf[3] = 0;
- macbuf[4] = 0;
- /* NOTE/TODO: This only allows 8 nics per machine! */
- macbuf[5] = (machine->serial_nr << 4) + (machine->nr_of_nics << 1);
-
- if (macbuf[0] & 1 || macbuf[5] & 1) {
- fatal("Internal error in net_generate_unique_mac().\n");
- exit(1);
+ /* Use a configured MAC address if available, or generate
+ something that seems to be reasonable. */
+ if (net_get_configured_mac (machine, machine->nr_of_nics, macbuf) != 0) {
+ // Special case: real SGI machines have 0x08 as their first
+ // byte, so let's mimic that.
+ macbuf[0] = machine->machine_type == MACHINE_SGI ? 0x08 : 0x10;
+ macbuf[1] = 0x20;
+ macbuf[2] = 0x30;
+ macbuf[3] = 0;
+ macbuf[4] = 0;
+ /* NOTE/TODO: This only allows 8 nics per machine! */
+ macbuf[5] = (machine->serial_nr << 4) + (machine->nr_of_nics << 1);
+
+ if (macbuf[0] & 1 || macbuf[5] & 1) {
+ fatal("Internal error in net_generate_unique_mac().\n");
+ exit(1);
+ }
}
/* TODO: Remember the mac addresses somewhere? */
diff --git a/src/core/main.c b/src/core/main.c
index f08f68c..0730dba 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -180,6 +180,7 @@ static void usage(bool longusage)
" ISO9660\n filesystem, -j sets the name of the"
" kernel to load.\n");
printf(" -L tapdev enable tap networking using device 'tapdev'\n");
+ printf(" -l mac,,, Comma-separated list of MAC addresses for all network adapters\n");
printf(" -M m emulate m MBs of physical RAM\n");
printf(" -N display nr of instructions/second average, at"
" regular intervals\n");
@@ -267,7 +268,8 @@ static void usage(bool longusage)
* Reads command line arguments.
*/
int get_cmd_args(int argc, char *argv[], struct emul *emul,
- char ***diskimagesp, int *n_diskimagesp, char **tap_devname)
+ char ***diskimagesp, int *n_diskimagesp, char **tap_devname,
+ char **mac_list)
{
int using_switch_e = 0, using_switch_E = 0;
bool using_switch_Z = false;
@@ -280,7 +282,7 @@ int get_cmd_args(int argc, char *argv[], struct emul *emul,
struct machine *m = emul_add_machine(emul, NULL);
const char *opts =
- "AC:c:Dd:E:e:GHhI:iJj:k:KL:M:Nn:Oo:p:QqRrSs:TtVvW:"
+ "AC:c:Dd:E:e:GHhI:iJj:k:KL:l:M:Nn:Oo:p:QqRrSs:TtVvW:"
#ifdef WITH_X11
"XxY:"
#endif
@@ -369,6 +371,9 @@ int get_cmd_args(int argc, char *argv[], struct emul *emul,
case 'K':
debugger_enter_at_end_of_run = true;
break;
+ case 'l':
+ *mac_list = strdup(optarg);
+ break;
case 'L':
*tap_devname = strdup(optarg);
break;
@@ -592,6 +597,7 @@ int main(int argc, char *argv[])
struct emul *emul;
bool using_config_file = false;
char *tap_devname = NULL;
+ char *mac_list = NULL;
char **diskimages = NULL;
int n_diskimages = 0;
int i;
@@ -640,7 +646,7 @@ int main(int argc, char *argv[])
settings_add(global_settings, "emul", 1,
SETTINGS_TYPE_SUBSETTINGS, 0, emul->settings);
- get_cmd_args(argc, argv, emul, &diskimages, &n_diskimages, &tap_devname);
+ get_cmd_args(argc, argv, emul, &diskimages, &n_diskimages, &tap_devname, &mac_list);
if (!skip_srandom_call) {
struct timeval tv;
@@ -678,6 +684,9 @@ int main(int argc, char *argv[])
return 1;
}
+ /* Add MAC address list to machine. */
+ emul->machines[0]->mac_list = strdup(mac_list);
+
/* Initialize one emul: */
if (!emul_simple_init(emul, tap_devname)) {
fprintf(stderr, "Could not initialize the emulation.\n");
I'd very much appreciate comments on the approach, or hints when
there's a better way.
Thanks,
Jan-Benedict
--
|