From: Visa Hankala Subject: Re: sys/cnmac: read HW address from DTS when available To: "Kirill A. Korinsky" Cc: tech@openbsd.org Date: Mon, 27 Apr 2026 15:41:48 +0000 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 > #include > > +#include > + > #include > #include > #include > @@ -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 >