Skip to content

Commit 8702deb

Browse files
authored
Merge pull request #281 from adnsio/vmnet-custom-mac-address
virtio-net: use mac address from pci configuration
2 parents d867f44 + ce698ad commit 8702deb

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

src/lib/pci_virtio_net_vmnet.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,15 @@
105105
(VIRTIO_NET_F_MAC | VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_STATUS | \
106106
VIRTIO_F_NOTIFY_ON_EMPTY)
107107

108+
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
109+
108110
/*
109111
* PCI config-space "registers"
110112
*/
111113
struct virtio_net_config {
112114
uint8_t mac[6];
113115
uint16_t status;
116+
int mac_provided;
114117
} __packed;
115118

116119
/*
@@ -253,6 +256,16 @@ vmn_create(struct pci_vtnet_softc *sc)
253256
return;
254257
}
255258

259+
if (sc->vsc_config.mac_provided) {
260+
char mac_str[18];
261+
262+
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
263+
sc->vsc_config.mac[0], sc->vsc_config.mac[1], sc->vsc_config.mac[2],
264+
sc->vsc_config.mac[3], sc->vsc_config.mac[4], sc->vsc_config.mac[5]);
265+
266+
xpc_dictionary_set_string(interface_param, vmnet_mac_address_key, mac_str);
267+
}
268+
256269
if (sscanf(xpc_dictionary_get_string(interface_param,
257270
vmnet_mac_address_key),
258271
"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
@@ -697,10 +710,28 @@ pci_vtnet_ping_ctlq(void *vsc, struct vqueue_info *vq)
697710
#endif
698711

699712
static int
700-
pci_vtnet_init(struct pci_devinst *pi, UNUSED char *opts)
713+
pci_vtnet_parsemac(char *mac_str, uint8_t *mac_addr)
714+
{
715+
struct ether_addr *ea;
716+
char zero_addr[ETHER_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 };
717+
718+
ea = ether_aton(mac_str);
719+
720+
if (ea == NULL || ETHER_IS_MULTICAST(ea->octet) ||
721+
memcmp(ea->octet, zero_addr, ETHER_ADDR_LEN) == 0) {
722+
fprintf(stderr, "Invalid MAC address: %s\n", mac_str);
723+
return (EINVAL);
724+
} else {
725+
memcpy(mac_addr, ea->octet, ETHER_ADDR_LEN);
726+
}
727+
728+
return (0);
729+
}
730+
731+
static int
732+
pci_vtnet_init(struct pci_devinst *pi, char *opts)
701733
{
702734
struct pci_vtnet_softc *sc;
703-
int mac_provided;
704735

705736
sc = calloc(1, sizeof(struct pci_vtnet_softc));
706737

@@ -718,11 +749,24 @@ pci_vtnet_init(struct pci_devinst *pi, UNUSED char *opts)
718749
sc->vsc_queues[VTNET_CTLQ].vq_notify = pci_vtnet_ping_ctlq;
719750
#endif
720751

721-
/*
722-
* Attempt to open the tap device and read the MAC address
723-
* if specified
724-
*/
725-
mac_provided = 0;
752+
if (opts != NULL) {
753+
int err;
754+
char *mac_str;
755+
char *tmp_str;
756+
757+
mac_str = strdup(opts);
758+
(void) strsep(&mac_str, ",");
759+
760+
tmp_str = strsep(&mac_str, "=");
761+
762+
if (!strcmp(tmp_str, "mac") && mac_str != NULL) {
763+
err = pci_vtnet_parsemac(mac_str, sc->vsc_config.mac);
764+
if (err != 0) {
765+
return (err);
766+
}
767+
sc->vsc_config.mac_provided = 1;
768+
}
769+
}
726770

727771
if (vmn_create(sc) == -1) {
728772
return (-1);

0 commit comments

Comments
 (0)