if_epair(4): use ether_gen_addr(9) for stable MAC address

Before this change epair interfaces get a random MAC. This does
not help dhcp/dyndns when an epair gets destroyed/recreated
after restart of a jail.

With this change:
$ sysctl net.link.epair.ether_gen_addr=0
$ ifconfig epair8 create > /dev/null; ifconfig epair8a | grep ether; ifconfig epair8b | grep ether; ifconfig epair8a destroy
	ether 02:cb:78:56:e4:0a
	ether 02:cb:78:56:e4:0b
$ ifconfig epair8 create > /dev/null; ifconfig epair8a | grep ether; ifconfig epair8b | grep ether; ifconfig epair8a destroy
	ether 02:8b:9b:6a:8f:0a
	ether 02:8b:9b:6a:8f:0b

$ sysctl net.link.epair.ether_gen_addr=1
$ ifconfig epair8 create > /dev/null; ifconfig epair8a | grep ether; ifconfig epair8b | grep ether; ifconfig epair8a destroy
	ether 58:9c:fc:10:2b:b4
	ether 58:9c:fc:00:39:10
$ ifconfig epair8 create > /dev/null; ifconfig epair8a | grep ether; ifconfig epair8b | grep ether; ifconfig epair8a destroy
	ether 58:9c:fc:10:2b:b4
	ether 58:9c:fc:00:39:10

A follow up commit will change the default to 1 in main.

Approved by:	bz,ivy,kp
MFC after:	2 weeks
Relnotes:	yes
Differential Revision: https://reviews.freebsd.org/D51157
This commit is contained in:
Ronald Klop 2025-07-03 18:33:03 +02:00
parent 6374c45fba
commit 590493c141

View file

@ -58,6 +58,7 @@
#include <sys/smp.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
#include <net/bpf.h>
@ -97,6 +98,15 @@ static unsigned int next_index = 0;
#define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx)
#define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx)
SYSCTL_DECL(_net_link);
static SYSCTL_NODE(_net_link, OID_AUTO, epair, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"Pair of virtual cross-over connected Ethernet-like interfaces");
static bool use_ether_gen_addr = false;
SYSCTL_BOOL(_net_link_epair, OID_AUTO, ether_gen_addr, CTLFLAG_RWTUN,
&use_ether_gen_addr, false,
"Generate MAC with FreeBSD OUI using ether_gen_addr(9)");
struct epair_softc;
struct epair_queue {
struct mtx mtx;
@ -495,6 +505,17 @@ epair_clone_match(struct if_clone *ifc, const char *name)
return (1);
}
static void
epair_generate_mac_byname(struct epair_softc *sc, uint8_t eaddr[])
{
struct ether_addr gen_eaddr;
int i;
ether_gen_addr_byname(if_name(sc->ifp), &gen_eaddr);
for (i = 0; i < ETHER_ADDR_LEN; i++)
eaddr[i] = gen_eaddr.octet[i];
}
static void
epair_clone_add(struct if_clone *ifc, struct epair_softc *scb)
{
@ -502,9 +523,12 @@ epair_clone_add(struct if_clone *ifc, struct epair_softc *scb)
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
ifp = scb->ifp;
/* Copy epairNa etheraddr and change the last byte. */
memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
eaddr[5] = 0x0b;
if (!use_ether_gen_addr) {
/* Copy epairNa etheraddr and change the last byte. */
memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
eaddr[5] = 0x0b;
} else
epair_generate_mac_byname(scb, eaddr);
ether_ifattach(ifp, eaddr);
if_clone_addif(ifc, ifp);
@ -719,7 +743,10 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len,
/* Finish initialization of interface <n>a. */
ifp = sca->ifp;
epair_setup_ifp(sca, name, unit);
epair_generate_mac(sca, eaddr);
if (!use_ether_gen_addr)
epair_generate_mac(sca, eaddr);
else
epair_generate_mac_byname(sca, eaddr);
ether_ifattach(ifp, eaddr);