Index | Thread | Search

From:
Visa Hankala <visa@hankala.org>
Subject:
Re: sys/cnmac: read HW address from DTS when available
To:
"Kirill A. Korinsky" <kirill@korins.ky>
Cc:
tech@openbsd.org
Date:
Mon, 27 Apr 2026 15:41:48 +0000

Download raw body.

Thread
On Mon, Apr 27, 2026 at 11:54:21AM +0200, Kirill A. Korinsky wrote:
> tech@,
> 
> I'd like to fix cnmac to read local-mac-address from the matching DTS
> Ethernet port node, selected by the port reg.
> 
> When it is missing, it keeps the old fallback.
> 
> Tested on Unifi ER4 (CN70xx/CN71xx) and Unifi USG (CN50xx) without any
> impact, and on Juniper SRX300 (CN70xx/CN71xx) where chandes are:
> 
> before diff:
> 
> octpip0 at simplebus0
> octgmx0 at octpip0 interface 0
> cnmac0 at octgmx0: port 0 SGMII, address d0:dd:49:e0:63:80
> octgmx1 at octpip0 interface 1: no active ports found
> octgmx2 at octpip0 interface 4
> cnmac1 at octgmx2: port 24 AGL, address 00:00:00:00:00:00
> 
> after diff:
> 
> octpip0 at simplebus0
> octgmx0 at octpip0 interface 0
> cnmac0 at octgmx0: port 0 SGMII, address d0:dd:49:e0:63:80
> octgmx1 at octpip0 interface 1: no active ports found
> octgmx2 at octpip0 interface 4
> cnmac1 at octgmx2: port 24 AGL, address d0:dd:49:e0:63:82

This diff changes MAC addresses on the EdgeRouter Pro (and probably
ER-8 too) by swapping the MACs as follows:

cnmac0 <-> cnmac4
cnmac1 <-> cnmac5
cnmac2 <-> cnmac6
cnmac3 <-> cnmac7

This presumably relates to the quirky order of port enumeration with
this EdgeRouter model. I think the Ubiquiti firmware enumerates the GMX
interfaces in swapped order so that the OS port numbering would match
with the front panel labels. OpenBSD does not perform such a swap.

However, with this diff the cnmac(4) ports should now get the same MAC
addresses that the original firmware would assign them.

OK visa@

> Index: sys/arch/octeon/dev/cn30xxgmx.c
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/cn30xxgmx.c,v
> diff -u -p -r1.56 cn30xxgmx.c
> --- sys/arch/octeon/dev/cn30xxgmx.c	22 Apr 2026 19:11:04 -0000	1.56
> +++ sys/arch/octeon/dev/cn30xxgmx.c	27 Apr 2026 09:31:27 -0000
> @@ -87,6 +87,7 @@ struct cn30xxgmx_port_ops {
>  int	cn30xxgmx_match(struct device *, void *, void *);
>  void	cn30xxgmx_attach(struct device *, struct device *, void *);
>  int	cn30xxgmx_print(void *, const char *);
> +int	cn30xxgmx_get_port_node(int, int);
>  void	cn30xxgmx_init(struct cn30xxgmx_softc *);
>  int	cn30xxgmx_rx_frm_ctl_xable(struct cn30xxgmx_port_softc *,
>  	    uint64_t, int);
> @@ -169,6 +170,22 @@ cn30xxgmx_match(struct device *parent, v
>  }
>  
>  int
> +cn30xxgmx_get_port_node(int node, int port)
> +{
> +	int child;
> +
> +	if (node == 0)
> +		return 0;
> +
> +	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
> +		if (OF_getpropint(child, "reg", (uint32_t)-1) == port)
> +			return child;
> +	}
> +
> +	return 0;
> +}
> +
> +int
>  cn30xxgmx_get_phy_phandle(int interface, int port, int *port_1000x,
>      int *disable_an)
>  {
> @@ -235,6 +252,7 @@ cn30xxgmx_attach(struct device *parent, 
>  	struct cn30xxgmx_softc *sc = (void *)self;
>  	struct cn30xxsmi_softc *smi;
>  	int i;
> +	int node;
>  	int phandle;
>  	int phy_addr;
>  	int port;
> @@ -268,6 +286,7 @@ cn30xxgmx_attach(struct device *parent, 
>  
>  	for (i = 0; i < sc->sc_nports; i++) {
>  		port_sc = &sc->sc_ports[i];
> +		node = cn30xxgmx_get_port_node(aa->aa_node, i);
>  		if (sc->sc_port_types[i] == GMX_AGL_PORT)
>  			port = 24;
>  		else
> @@ -330,6 +349,7 @@ cn30xxgmx_attach(struct device *parent, 
>  		gmx_aa.ga_name = "cnmac";
>  		gmx_aa.ga_portno = port_sc->sc_port_no;
>  		gmx_aa.ga_port_type = sc->sc_port_types[i];
> +		gmx_aa.ga_node = node;
>  		gmx_aa.ga_gmx = sc;
>  		gmx_aa.ga_gmx_port = port_sc;
>  		gmx_aa.ga_phy_addr = phy_addr;
> Index: sys/arch/octeon/dev/cn30xxgmxvar.h
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/cn30xxgmxvar.h,v
> diff -u -p -r1.15 cn30xxgmxvar.h
> --- sys/arch/octeon/dev/cn30xxgmxvar.h	22 Apr 2026 19:11:04 -0000	1.15
> +++ sys/arch/octeon/dev/cn30xxgmxvar.h	27 Apr 2026 09:31:27 -0000
> @@ -95,6 +95,7 @@ struct cn30xxgmx_attach_args {
>  	const char		*ga_name;
>  	int			ga_portno;
>  	int			ga_port_type;
> +	int			ga_node;
>  	struct cn30xxsmi_softc	*ga_smi;
>  	int			ga_phy_addr;
>  
> Index: sys/arch/octeon/dev/if_cnmac.c
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/if_cnmac.c,v
> diff -u -p -r1.88 if_cnmac.c
> --- sys/arch/octeon/dev/if_cnmac.c	22 Apr 2026 19:11:04 -0000	1.88
> +++ sys/arch/octeon/dev/if_cnmac.c	27 Apr 2026 09:31:27 -0000
> @@ -51,6 +51,8 @@
>  #include <sys/endian.h>
>  #include <sys/atomic.h>
>  
> +#include <dev/ofw/openfirm.h>
> +
>  #include <net/if.h>
>  #include <net/if_media.h>
>  #include <netinet/in.h>
> @@ -120,6 +122,7 @@ void	cnmac_ipd_init(struct cnmac_softc *
>  void	cnmac_pko_init(struct cnmac_softc *);
>  
>  void	cnmac_board_mac_addr(uint8_t *);
> +int	cnmac_port_mac_addr(int, uint8_t *);
>  
>  int	cnmac_mii_readreg(struct device *, int, int);
>  void	cnmac_mii_writereg(struct device *, int, int, int);
> @@ -277,7 +280,8 @@ cnmac_attach(struct device *parent, stru
>  	 */
>  	sc->sc_ip_offset = 0/* XXX */;
>  
> -	cnmac_board_mac_addr(sc->sc_arpcom.ac_enaddr);
> +	if (cnmac_port_mac_addr(ga->ga_node, sc->sc_arpcom.ac_enaddr) != 0)
> +		cnmac_board_mac_addr(sc->sc_arpcom.ac_enaddr);
>  	printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
>  
>  	ml_init(&sc->sc_sendq);
> @@ -386,6 +390,17 @@ cnmac_pko_init(struct cnmac_softc *sc)
>  }
>  
>  /* ---- XXX */
> +
> +int
> +cnmac_port_mac_addr(int node, uint8_t *enaddr)
> +{
> +	if (node == 0)
> +		return 1;
> +	if (OF_getprop(node, "local-mac-address", enaddr, ETHER_ADDR_LEN) ==
> +	    ETHER_ADDR_LEN)
> +		return 0;
> +	return 1;
> +}
>  
>  void
>  cnmac_board_mac_addr(uint8_t *enaddr)
> Index: sys/arch/octeon/dev/iobusvar.h
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/iobusvar.h,v
> diff -u -p -r1.5 iobusvar.h
> --- sys/arch/octeon/dev/iobusvar.h	20 May 2024 23:20:29 -0000	1.5
> +++ sys/arch/octeon/dev/iobusvar.h	27 Apr 2026 09:31:27 -0000
> @@ -36,6 +36,7 @@ extern bus_space_t iobus_tag;
>  struct iobus_attach_args {
>  	char		*aa_name;
>  	int		aa_unitno;
> +	int		aa_node;
>  
>  	bus_addr_t	aa_addr;
>  	int		aa_irq;
> Index: sys/arch/octeon/dev/octeon_iobus.c
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/octeon_iobus.c,v
> diff -u -p -r1.28 octeon_iobus.c
> --- sys/arch/octeon/dev/octeon_iobus.c	20 May 2024 23:17:10 -0000	1.28
> +++ sys/arch/octeon/dev/octeon_iobus.c	27 Apr 2026 09:31:27 -0000
> @@ -231,6 +231,7 @@ iobussearch(struct device *parent, void 
>  	aa.aa_addr = cf->cf_loc[0];
>  	aa.aa_irq  = cf->cf_loc[1];
>  	aa.aa_unitno = cf->cf_unit;
> +	aa.aa_node = 0;
>  
>  	/* No address specified, try to look it up. */
>  	if (aa.aa_addr == -1) {
> Index: sys/arch/octeon/dev/octpip.c
> ===================================================================
> RCS file: /home/cvs/src/sys/arch/octeon/dev/octpip.c,v
> diff -u -p -r1.3 octpip.c
> --- sys/arch/octeon/dev/octpip.c	8 Sep 2020 13:54:48 -0000	1.3
> +++ sys/arch/octeon/dev/octpip.c	27 Apr 2026 09:31:27 -0000
> @@ -82,6 +82,7 @@ octpip_attach(struct device *parent, str
>  		iaa.aa_addr = addr;
>  		iaa.aa_irq = -1;
>  		iaa.aa_unitno = ifindex;
> +		iaa.aa_node = node;
>  		config_found(self, &iaa, octpip_print);
>  	}
>  }
> 
> -- 
> wbr, Kirill
>