Bug 262407

Summary: net/realtek-re-kmod: kernel panic when generating MAC address
Product: Ports & Packages Reporter: Evgeni Golov <evgeni>
Component: Individual Port(s)Assignee: Alex Dupre <ale>
Status: Closed FIXED    
Severity: Affects Only Me CC: grahamperrin, kib, pi, s199p.wa1k9r
Priority: --- Keywords: crash, needs-qa
Version: LatestFlags: bugzilla: maintainer-feedback? (ale)
grahamperrin: maintainer-feedback? (kib)
Hardware: Any   
OS: Any   

Description Evgeni Golov 2022-03-07 19:48:51 UTC
Ohai,

there exists hardware (like [1]) that has no ethernet address burned into the EEPROM. Realteks driver (contrary to the one in the FreeBSD kernel, see #262406) tries to accommodate for that by generating a random mac address:

3890-        if (!is_valid_ether_addr(eaddr)) {
3891-                device_printf(dev,"Invalid ether addr: %6D\n", eaddr, ":");
3892:                random_ether_addr(eaddr);
3893-                device_printf(dev,"Random ether addr: %6D\n", eaddr, ":");
3894-        }

However, the net/realtek-re-kmod port patches (in files/patch-if__re.c) the `random_ether_addr` call to be 
  ether_gen_addr(sc->re_ifp, (struct ether_addr *)eaddr);
instead.

This leads to a crash on my HW, with the following trace:
KDB: stack backtrace:
#0 0xffff00000050d058 at kdb_backtrace+0x60
#1 0xffff0000004b7228 at vpanic+0x184
#2 0xffff0000004b70a0 at panic+0x44
#3 0xffff000000824d2c at data_abort+0x1d8
#4 0xffff000000805078 at handle_el1h_sync+0x78
#5 0xffff00000051434c at kvprintf+0xbb4
#6 0xffff00000051434c at kvprintf+0xbb4
#7 0xffff000000515100 at vsnprintf+0x3c
#8 0xffff0000005c70c8 at vasprintf+0x4c
#9 0xffff0000005c7190 at asprintf+0x40
#10 0xffff0000005eb284 at ether_gen_addr+0x74
#11 0xffff000001222294 at re_attach+0x1b90
#12 0xffff0000004f9254 at device_attach+0x400
#13 0xffff0000004fa770 at bus_generic_attach+0x4c
#14 0xffff000000236e08 at pci_attach+0xe0
#15 0xffff0000004f9254 at device_attach+0x400
#16 0xffff0000004fa770 at bus_generic_attach+0x4c
#17 0xffff0000004f9254 at device_attach+0x400

I am not exactly sure *what* triggers this. At first I thought it'd be the cast of eaddr, but that *should* work.
ether_gen_addr *does* call asprintf, so it might be that?

Reverting to the original random code from Realtek works.

Thanks!

[1] https://www.dfrobot.com/product-2242.html
Comment 1 Alex Dupre freebsd_committer freebsd_triage 2022-03-08 08:37:26 UTC
@kib, any idea about the cause of the failure?
Comment 2 Konstantin Belousov freebsd_committer freebsd_triage 2022-11-11 06:00:54 UTC
This is due to ether_gen_addr() using if_name(), most likely.

Try this:
diff --git a/if_re.c b/if_re.c
index 541af57..95da310 100644
--- a/if_re.c
+++ b/if_re.c
@@ -4978,6 +4978,24 @@ static int re_attach(device_t dev)
         re_reset(sc);
         RE_UNLOCK(sc);
 
+#if OS_VER < VERSION(6,0)
+        ifp = &sc->arpcom.ac_if;
+#else
+        ifp = sc->re_ifp = if_alloc(IFT_ETHER);
+        if (ifp == NULL) {
+                device_printf(dev, "can not if_alloc()\n");
+                error = ENOSPC;
+                goto fail;
+        }
+#endif
+        ifp->if_softc = sc;
+#if OS_VER < VERSION(5,3)
+        ifp->if_unit = unit;
+        ifp->if_name = "re";
+#else
+        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+#endif
+
         /* Get station address. */
         RE_LOCK(sc);
         re_get_hw_mac_address(sc, eaddr);
@@ -5076,23 +5094,6 @@ static int re_attach(device_t dev)
         sc->re_tx_cstag =1;
         sc->re_rx_cstag =1;
 
-#if OS_VER < VERSION(6,0)
-        ifp = &sc->arpcom.ac_if;
-#else
-        ifp = sc->re_ifp = if_alloc(IFT_ETHER);
-        if (ifp == NULL) {
-                device_printf(dev, "can not if_alloc()\n");
-                error = ENOSPC;
-                goto fail;
-        }
-#endif
-        ifp->if_softc = sc;
-#if OS_VER < VERSION(5,3)
-        ifp->if_unit = unit;
-        ifp->if_name = "re";
-#else
-        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-#endif
         ifp->if_mtu = ETHERMTU;
         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
         ifp->if_ioctl = re_ioctl;
Comment 3 Konstantin Belousov freebsd_committer freebsd_triage 2022-11-11 06:08:34 UTC
Perhaps this variant is less intrusive

diff --git a/if_re.c b/if_re.c
index 541af57..0e99dfd 100644
--- a/if_re.c
+++ b/if_re.c
@@ -4978,25 +4978,8 @@ static int re_attach(device_t dev)
         re_reset(sc);
         RE_UNLOCK(sc);
 
-        /* Get station address. */
-        RE_LOCK(sc);
-        re_get_hw_mac_address(sc, eaddr);
-        RE_UNLOCK(sc);
-
-        /*
-         * A RealTek chip was detected. Inform the world.
-         */
-        device_printf(dev,"version:%s\n", RE_VERSION);
-        device_printf(dev,"Ethernet address: %6D\n", eaddr, ":");
-        printf("\nThis product is covered by one or more of the following patents: \
-           \nUS6,570,884, US6,115,776, and US6,327,625.\n");
-
         sc->re_unit = unit;
 
-#if OS_VER < VERSION(6,0)
-        bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
-#endif
-
         if (sc->re_type == MACFG_3) {	/* Change PCI Latency time*/
                 pci_write_config(dev, RE_PCI_LATENCY_TIMER, 0x40, 1);
         }
@@ -5119,6 +5102,23 @@ static int re_attach(device_t dev)
         ifp->if_capenable = ifp->if_capabilities;
         ifp->if_capenable &= ~(IFCAP_WOL_UCAST | IFCAP_WOL_MCAST);
 
+        /* Get station address. */
+        RE_LOCK(sc);
+        re_get_hw_mac_address(sc, eaddr);
+        RE_UNLOCK(sc);
+
+        /*
+         * A RealTek chip was detected. Inform the world.
+         */
+        device_printf(dev,"version:%s\n", RE_VERSION);
+        device_printf(dev,"Ethernet address: %6D\n", eaddr, ":");
+        printf("\nThis product is covered by one or more of the following patents: \
+           \nUS6,570,884, US6,115,776, and US6,327,625.\n");
+
+#if OS_VER < VERSION(6,0)
+        bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
+#endif
+
         RE_LOCK(sc);
         re_phy_power_up(dev);
         re_hw_phy_config(sc);
Comment 4 Evgeni Golov 2022-11-14 11:21:37 UTC
In the meantime, I got the in-kernel driver working as needed (see https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=262406 and https://reviews.freebsd.org/D34485), so I'm not currently using the kmod and facing this issue.

Konstantin, do you want me to test your patch on my HW to verify it solves the issue?
Comment 5 Alex Dupre freebsd_committer freebsd_triage 2022-11-14 12:05:35 UTC
Yes, if you can test the patch it'd be quite useful, so I can update the port.
Comment 6 s199p.wa1k9r 2023-07-15 15:05:30 UTC
The port version is 198.04_2.
When calling the random_ether_addr(eaddr) function, the kernel still crashes.
Is there a patch for the current diver version.
I'm in to run tests
Comment 7 s199p.wa1k9r 2023-07-15 15:45:22 UTC
Oh, sorry ether_gen_addr(sc->re_ifp, (struct ether_addr *)eaddr);
Comment 8 Alex Dupre freebsd_committer freebsd_triage 2023-07-17 09:01:22 UTC
Updated patch here: https://github.com/alexdupre/rtl_bsd_drv/commit/422aad16b625bb4f4036749452164f4a4fba4108

Let me know if it fixes the issue.
Comment 9 s199p.wa1k9r 2023-07-17 15:34:33 UTC
root@NanoPC-T6:~ # ifconfig 
re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=201b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,WOL_MAGIC>
	ether 58:9c:fc:10:81:7a
	inet 192.168.1.180 netmask 0xffffff00 broadcast 192.168.1.255
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active
re1: flags=8803<UP,BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
	options=201b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,WOL_MAGIC>
	ether 58:9c:fc:10:d2:a1
	inet 192.168.0.180 netmask 0xffffff00 broadcast 192.168.0.255
	media: Ethernet autoselect
	status: no carrier
--
Thank you. Now it works reliably.
Tested on aarch64 SoC Rockchip RK3588
Speed test using iperf3 showed about 1.3Gbps.
Comment 10 s199p.wa1k9r 2023-07-17 15:36:52 UTC
Is it possible to achieve high speeds on AMD64?
Comment 11 Alex Dupre freebsd_committer freebsd_triage 2023-07-17 15:46:56 UTC
(In reply to s199p.wa1k9r from comment #10)

Do you have any evidence that it's not achieving high speed on AMD64?

Reaching 1.3Gbps on a 1000baseT link seems too good :-)
Comment 12 commit-hook freebsd_committer freebsd_triage 2023-07-17 15:52:41 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/ports/commit/?id=7845799f666b35881b8387bd1ae5aba68d666b61

commit 7845799f666b35881b8387bd1ae5aba68d666b61
Author:     Alex Dupre <ale@FreeBSD.org>
AuthorDate: 2023-07-17 15:50:18 +0000
Commit:     Alex Dupre <ale@FreeBSD.org>
CommitDate: 2023-07-17 15:50:18 +0000

    net/realtek-re-kmod: fix kernel panic when generating MAC address.

    PR:             262407
    Reported by:    Evgeni Golov <evgeni@debian.org>
    Submitted by:   kib

 net/realtek-re-kmod/Makefile | 4 ++--
 net/realtek-re-kmod/distinfo | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)
Comment 13 s199p.wa1k9r 2023-07-17 18:05:26 UTC
(In reply to Alex Dupre from comment #11)

I tested at home with my hack.
There is a 2.5Gbps switch
I tested your patch in the office. There is no 2.5Gbps here.
It's all fair, don't worry