Commit Graph
71288 Commits
Author SHA1 Message Date
Gennaro Cimmino 601fa13e89 realtek: l3: leave routes from IPv6 RAs to the kernel
A router advertisement adds its routes with RTF_ADDRCONF: on-link
prefixes, which have no gateway and are left out already, the default
route, also left out, and with CONFIG_IPV6_ROUTE_INFO the Route
Information routes. Such routes never become multipath siblings
(rt6_qualify_for_ecmp()), so the routes several routers advertise for
one prefix sit side by side and the kernel picks among them at lookup
time (rt6_select()). The driver only hears of the route at the head of
the list, and when a router changes its preference the route is
updated in place, with no event.

Leave RTF_ADDRCONF routes to the kernel. OpenWrt builds the kernel
without CONFIG_IPV6_ROUTE_INFO, so none of the routes its router
advertisements add is handled differently.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled.
No router advertisement can create such a route with OpenWrt's kernel,
so a bench-only tool added one through the legacy SIOCADDRT ioctl,
which keeps RTF_ADDRCONF in the flags. On main it is programmed to
forward and marked offloaded; with this change it gets the trap row a
route left to the kernel gets, is not marked offloaded, and the echoes
sent into it still all reach its gateway. A twin route to another
prefix without the flag is offloaded on both.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25602
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 18:53:02 +02:00
Gennaro Cimmino df85424b93 realtek: l3: keep main /32s out of a local address's entry
The host table holds one entry per IPv4 address, found by the address
alone. A /32 in main for an address of the switch shared that entry
with the local route: whichever wrote last owned it, a neighbour update
of the main route turned the local trap into forwarding, and deleting
the main route took the entry from the local one. The kernel looks the
local table up first, so the address is the switch's for as long as it
holds it.

While a local route holds an address, a host route from main for it
leaves the entry alone - on add, neighbour update, trap and delete -
and keeps its state in memory. When the local route goes, the main
route writes its entry back as it last stood.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this and the previous commit. A /32 route
through a gateway in hardware, then the same address added to the
switch, and 5 echoes to it:
- after a neighbour update of the gateway, main turned the address's
  entry into forwarding and sent all 5 to the gateway, unanswered;
  now the switch answers all 5.
- with a /24 through the gateway covering it and the /32 route
  deleted, main took the address's entry away and the /24 forwarded
  all 5; now the switch answers all 5.
- with a /24 through another gateway covering it and the address
  deleted, main took the /32 route's entry with it and the /24 sent
  all 5 to that other gateway; now the /32 route forwards all 5 to
  its own.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25598
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 18:47:46 +02:00
Gennaro Cimmino d3301f3ea0 realtek: l3: place local table rows ahead of main's
The kernel looks the local table up before main, so an address of the
switch is delivered to it even when main holds a route of the same
length to that address. The hardware answers with the first prefix row
that matches, and a route is placed after every row of its length or
longer: whichever of the two came first won, and a /128 route in main
added before the address forwarded the address's traffic away.

Place a local table entry after the longer rows only, ahead of main's
of the same length. Main's row stays, and answers again once the
address is gone.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this and the next commit, which only touches
the IPv4 host table. fd00:9f::1/128 through a gateway in hardware,
then fd00:9f::1/64 added to the switch, and 5 echoes to the address:
main left the route's row ahead of the address's and forwarded all 5
to the gateway, unanswered; now the switch answers all 5. With the
address gone again, the route forwards all 5 to its gateway on both.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25598
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 18:47:46 +02:00
Karsten Sperling 8a6ae95526 hostapd: mbedtls EAP-TLS peer 3.6.3+ compatibility
Mbed TLS 3.6.3 (and 2.28.10) introduced the requirement to set or
explicitly clear the hostname when verifying a server certificate,
otherwise verification fails with
MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME. Clearing the
hostname allows EAP-TLS to work correctly in the peer / supplicant role
on those Mbed TLS versions.

https://mbed-tls.readthedocs.io/en/latest/kb/attacks/ssl_set_hostname/

Signed-off-by: Karsten Sperling <ksperling@apple.com>
Link: https://github.com/openwrt/openwrt/pull/25552
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 17:52:54 +02:00
Karsten Sperling 9e21f779cb hostapd: fix inverted test in tls_mbedtls_set_ciphers
tls_mbedtls_set_ciphers() contains logic intended to handle cipher name
mapping cases where the Mbed TLS name carries a trailing "-SHA256" that
the OpenSSL name omits, e.g. the OpenSSL name
"ECDHE-RSA-CHACHA20-POLY1305" corresponds to the Mbed TLS name
"TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256". The os_memcmp()
expression for this suffix check was missing a "== 0", i.e. the logic
was inverted.

This means intended cases like "ECDHE-ECDSA-CHACHA20-POLY1305" were
incorrectly rejected (an unmatched name makes tls_mbedtls_set_ciphers()
fail), while accepting bogus mappings like "ECDHE-RSA-AES256-GCM" ->
"ECDHE-RSA-AES256-GCM-SHA384" or "ECDHE-ECDSA-AES" ->
"ECDHE-ECDSA-AES256-CCM". (Fortunately no valid OpenSSL suite names were
accepted with a bogus mapping.)

Signed-off-by: Karsten Sperling <ksperling@apple.com>
Link: https://github.com/openwrt/openwrt/pull/25552
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 17:52:54 +02:00
Karsten Sperling 218dae245a hostapd: mbedtls check_cert_subject uninitialized read
tls_mbedtls_match_dn_field() populates one struct mlistoid per component
of the check_cert_subject string, but never initializes the prefix flag,
which is only assigned when the value ends in '*'. Whether a component
without a wildcard was matched as a prefix therefore depended on
leftover stack contents, e.g. check_cert_subject="O=w1.f" could be
accepted for an Organization of "w1.fi".

Found by ap_wpa2_eap_ttls_pap_check_cert_subject_neg, which happens to
check "C=FI1*" immediately before "O=w1.f".

Signed-off-by: Karsten Sperling <ksperling@apple.com>
Link: https://github.com/openwrt/openwrt/pull/25552
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 17:52:54 +02:00
Manuel Fombuena af6b5f161f kernel: leds-st1202: load the module in preinit
OpenWrt sources diag.sh at the preinit_main hook stage (02_default_set_state),
resolving LED aliases from the device tree so that set_state() can blink the
boot LED through the preinit and preinit_regular phases before init takes
over. For that to work the LED driver must be present before the preinit
scripts run.

Without the boot flag, AutoProbe only places the module in etc/modules.d,
which is loaded by /etc/init.d/boot once preinit has finished. By that
point the entire preinit LED window has passed and the boot indication on
any ST LED1202-backed LED is silently skipped.

Set the boot flag so the module is also linked into etc/modules-boot.d,
which procd loads before running the preinit scripts. The previous commits
bring the driver to a state where loading it at early boot is appropriate.

Assisted-by: LLM
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23456
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 17:15:03 +02:00
Manuel Fombuena b35baa6829 qualcommax: ipq807x: add default LED configuration for linksys_mx4200v2
Register the three status LEDs of the ST LED1202 controller in the board
default configuration so they are exposed to userspace via UCI and LuCI,
allowing users to customise LED behaviour without manual sysfs interaction.

Blue is enabled by default; red and green are off.

Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23456
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 17:15:03 +02:00
Manuel Fombuena 0b1af6d596 qualcommax: ipq807x: fix LED controller assignment for linksys_mx4x00 devices
The NXP PCA9633 LED controller was defined in the shared ipq8174-mx4x00.dtsi,
but the MX4200v2 uses a different controller — the ST LED1202 (I2C address
0x58) — instead of the PCA9633 (0x62) used by MX4200v1, MX4300, and HomeWRK.

Move the LED controller node out of the shared DTSI into each device's own
DTS file.

Fix kmod-leds-pca963x being pulled in for all linksys_mx devices by assigning
LED driver packages explicitly per device: kmod-leds-pca963x for MX4200v1,
MX4300, MX5300, and MX8500; kmod-leds-st1202 for MX4200v2.

Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23456
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 17:15:03 +02:00
Hauke Mehrtens b2cca02d47 ead: fix out-of-bounds writes in the client message handlers
ead-client trusts several length and index fields taken straight from
the network when handling server responses, before authentication has
completed.  Since the client sends its requests as UDP broadcasts and
never validates the origin of the replies, any host on the same L2
segment can spoof the whole handshake and hit these paths.

handle_prime() copies sb->len bytes into saltbuf[MAXSALTLEN] (32 bytes)
without checking the length, and passes sb->prime to t_getpreparam()
without a range check.  Both come from the wire, so a salt length up to
255 overflows saltbuf and a prime index up to 255 reads (and writes)
out of bounds in the precompiled parameter table.  This is
GHSA-mq4v-mf82-24rr.

handle_b() computes the copy length as msg->len - sizeof(number) and
memcpy()s it into bbuf[MAXPARAMLEN] with no bounds check.  msg->len is
attacker controlled and only capped by the 1500 byte receive buffer, so
up to 1479 bytes land in the 256 byte bbuf.  A msg->len of 0 makes the
signed length -1, which memcpy() treats as SIZE_MAX.  This is
GHSA-8f8g-5c8x-8mhh.

handle_pong() writes the NUL terminator at pong->name[len] using an
unchecked length, allowing a one byte write past msgbuf, and the receive
loop's length check could wrap for a large msg->len.

Bound every length against its destination buffer and range check the
prime index, mirroring the checks already present on the daemon side in
ead.c (handle_send_a(), commit 63c0767f3d).  ead-client is not
installed into images by the ead package, only the daemon is, so this
only affects administrators who build and run the client by hand.

Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-mq4v-mf82-24rr
Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-8f8g-5c8x-8mhh
Fixes: 2d86ea2a1d ("add the 'ead' package (emergency access daemon), which can provide remote access to your device, even if the ip and firewall settings are broken")
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/openwrt/pull/25492
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 17:09:00 +02:00
Hauke Mehrtens 09538fccfc rpcd: update to Git HEAD (2026-10-04)
d99f703e4035 session: stop naming runtime files after the session id

Link: https://github.com/openwrt/openwrt/pull/25587
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 17:05:52 +02:00
Grische 195c2ce324 build: fix image headers silently truncated with uutils coreutils
Build/elx-header and Build/znet-header convert a hex string into \xHH
escape sequences using `fold -s2`. This relies on the obsolete -WIDTH
option syntax of GNU fold, which parses "-s2" as "-s -2". uutils
coreutils does not support this syntax and fails with:

  error: unexpected argument '-2' found

    tip: to pass '-2' as a value, use '-- -2'

Since fold writes nothing to stdout in this case, the command
substitution expands to an empty string. The following
`dd bs=N count=1 conv=sync` then writes zero bytes, because conv=sync
only pads partial input blocks and never pads empty input. The header
field is dropped entirely, and all subsequent fields move to lower
offsets.

The build still succeeds, because the failure happens inside the
subshell which is then handed to echo.
The malformed images are only rejected when a device tries to
boot them.

For example, on the Zyxel WSM20, the missing payload size field in the
znet-header moves the 0x12345678 magic and the payload to unexpected
offsets. The bootloader then rejects the image, even though sysupgrade
accepted it.

This affects all builds on Ubuntu 25.10 and later, because these
releases use uutils coreutils by default.

Replace `fold -s2` with `fold -w2`, which is the documented way to set
the line width and produces identical output with GNU fold.

Affected devices:
- Build/znet-header is used in all images of the Zyxel WSM20 and the
  ELECOM WRC-X1800GS
- Build/elx-header is used in the factory images of the ELECOM
  WAB-I1750-PS, WAB-S1167-PS, WAB-S600-PS, WRC-2533GHBK-I and
  WRC-2533GHBK2-T, the I-O DATA WN-AC1167GR, WN-AC733GR3 and WNPR2600G,
  the Edimax RA21S and RG21S, and the D-Link DAP-X1860 A1

Signed-off-by: Grische <github@grische.xyz>
Assisted-by: Claude:claude-opus-5
Link: https://github.com/openwrt/openwrt/pull/25410
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 16:34:06 +02:00
John Audia db9616b9af kernel: bump 6.18 to 6.18.55
Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.18.55

Removed upstreamed:
  linux/generic/backport-6.18/707-v7.3-net-phylink-record-the-PHY-only-once-bringup-cannot-.patch[1]

All other patches automatically rebased via update_kernel.sh

1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v6.18.55&id=4e7a4af364c2048bafb213bf0ef4a89dcbe1bfd4

Build system: x86/64
Build-tested: x86/64-glibc
Run-tested: x86/64-glibc

Signed-off-by: John Audia <therealgraysky@proton.me>
Link: https://github.com/openwrt/openwrt/pull/25551
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 15:57:54 +02:00
Shiji Yang fc4c9e6ff7 kernel: bump 6.12 to 6.12.112
Changelog: https://cdn.kernel.org/pub/linux/kernel/v6.x/ChangeLog-6.12.112

Manually rebased patches:
- generic/backport-6.12/720-05-v6.13-net-phy-mediatek-Move-LED-helper-functions-into-mtk-.patch[1]
- generic/pending-6.12/700-netfilter-nft_flow_offload-handle-netdevice-events-f.patch[2]

All other patches are automatically refreshed.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=298fddcfd19422cb09861051ff8f8755e15a1372
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8274cdc5f9c57e17ed77fc4ba76212536c840f25
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25553
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 15:32:19 +02:00
Gennaro Cimmino 255b53f9c9 realtek: l3: count IPv6 source-specific routes per source
A source-specific route matches only the packets from its source, and
the hardware matches on the destination alone, so the driver traps the
destination of every such route. All of them shared one trap row with
one member count, which each add overwrote: deleting one of two
source-specific routes to a prefix took the row from the other, and an
add of the route without a source to that prefix replaced the trap
with a forwarding row, which then sent the traffic of every source to
its gateway. A source-specific route added over a forwarding row took
that row out, and deleting it again left the destination without one.

Keep the members of each source apart on the trap row, next to those of
the route without a source, and take the row out only when none is
left. The route without a source joins the trap while source-specific
routes remain, and keeps it after they are gone until its next event,
as a multipath route keeps its trap after a member leaves. The error
that stood in for this goes.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this change. fd00:9e::/32 through one gateway
in hardware, a /48 inside it, and 5 echoes into the /48 from a host in
the source of the first route below, which the CPU routes back to it:
- two source-specific routes, then one deleted: main took the row away
  and all 5 echoes reached the /32's gateway; now the row stays and
  none do.
- a route without a source through the /32's gateway, added after a
  source-specific one: main forwarded all 5 to that gateway whatever
  their source; now the row stays a trap and none go there. Deleting
  that route left no row on main; the trap stays now.
- a source-specific route added and deleted over a forwarding route
  without a source: main left no row and all 5 reached the /32's
  gateway; now a trap stays and none do.
A default route with a source gets no row on either.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25583
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 14:04:09 +02:00
Denis Faizullin 13f1e1c66d ramips: add support for TP-Link EX220 v1 (NAND)
TP-Link EX220 v1 as distributed by the Russian ISP MTS, labelled
"EX220(RU)MTS) Ver:1.30". It carries the same model name as the already
supported tplink,ex220-v1, but it is a different board: 128 MB of
parallel NAND managed by NMBM instead of 16 MB of SPI-NOR, and an entirely
different flash layout. The bootloader tells the two apart - on this
revision U-Boot prints "NAND:  128 MiB" followed by "NMBM has been
successfully attached".

Hardware specification:
- SoC: MediaTek MT7621AT (MIPS 1004Kc, ver 1 eco 3)
- RAM: 128 MB DDR3 (chip hidden under the shielding can)
- Flash: 128 MB parallel NAND, ESMT F59L1G81MB, NMBM managed
  (the driver identifies the chip as "ESMT PSU1GA30DT")
- WiFi: MediaTek MT7915E, DBDC, 2x2 2.4 GHz + 2x2 5 GHz (AX1800)
- Ethernet: MediaTek MT7530, 5x 10/100/1000 Mbps (4x LAN + 1x WAN)
- LEDs: 7x GPIO - power, LAN, WAN green, WAN amber, WLAN 2.4 GHz,
  WLAN 5 GHz, WPS
- Buttons: 2x tactile - reset, WPS
- UART: 4 unpopulated through holes on the solder side of the board,
  beside the silver factory sticker, with no silkscreen designator.
  Counting from the hole furthest from the ethernet ports: pin 1 TX,
  pin 2 RX, pin 3 GND, pin 4 unused - leave it unconnected.
  115200 8N1, 3.3 V.
- Power: 12 VDC, 1 A

MAC addresses:
  LAN    f0:a7:31:xx:xx:xx   misc_ro @ 0x5c50bc, matches the label
  WAN    f0:a7:31:xx:xx:xx   same as LAN
  2.4G   label MAC + 2
  5G     label MAC + 3

The radio calibration lives in the misc_ro partition, which holds a
JFFS2 filesystem with five files named after their original flash
offsets. The largest one carries the MT7915 EEPROM at offset 0x90000,
so 11-mt76-caldata mounts the partition read-only and copies it out.
Reading it needs CONFIG_JFFS2_ZLIB - the vendor compressed those nodes
with zlib, which OpenWrt does not build in by default.

It is worth the kernel option. With the factory calibration the client
reports -44 dBm at half a metre and negotiates HE-MCS 11; with the
generic default EEPROM the very same link reports -82 dBm and settles
at HE-MCS 3, and a local transfer peaks at 541 instead of 692 Mbit/s.

The vendor bootloader loads a FIT image from the fixed address
0xd00000 and does not evaluate partition names, so the vendor firmware
slot is split into a raw kernel partition and a UBI partition holding
rootfs and rootfs_data.

Flash instructions:

The vendor web interface offers no way in, so the first installation is
done over the serial console.

1. Open the case and attach a 3.3 V USB-to-serial adapter to the 4-pin
   header described above.
2. Power the board up and interrupt the bootloader by pressing any key
   when it prints "Hit any key to stop autoboot".
3. Load the initramfs image into RAM over YMODEM:

     loady 0x84000000

   Send openwrt-ramips-mt7621-tplink_ex220-v1-nand-initramfs-kernel.bin
   using the YMODEM transfer of your terminal program - this takes
   about 11 minutes at 115200 baud - and boot it:

     bootm 0x84000000

   Do not raise the bootloader console speed to shorten the transfer:
   with the console set to 921600 baud the kernel hangs while taking
   the UART over from the bootloader, leaving nothing after the 16550A
   line, and the watchdog resets the board.
4. The running system serves 192.168.1.1/24 on the LAN ports. Transfer
   openwrt-ramips-mt7621-tplink_ex220-v1-nand-squashfs-sysupgrade.bin
   to /tmp and install it:

     sysupgrade -n /tmp/openwrt-*-ex220-v1-nand-squashfs-sysupgrade.bin

   The board reboots into OpenWrt on its own; later updates use
   sysupgrade as usual.

Reverting to stock:

The second firmware slot ships empty, so there is nothing to fall back
to - take a backup while the initramfs image of step 3 is running, ie
before step 4:

     cat /dev/mtd4 /dev/mtd5 > /tmp/stock.bin

and copy it off the device. To restore it, boot the initramfs image
again and write it back:

     dd if=stock.bin bs=1M count=4 | mtd write - kernel
     dd if=stock.bin bs=1M skip=4 | mtd write - ubi

Signed-off-by: Denis Faizullin <triplexit.help@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24831
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:52:27 +02:00
Manuel Fombuena 9824d07c1d generic: add pending leds-st1202 hardware-accelerated blink support
Add patch queued in for-leds-next adding hardware-accelerated blink
support for the ST LED1202 driver. Applied to both pending-6.12 and
pending-6.18.

Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23455
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:43:09 +02:00
Manuel Fombuena 66644a5ab0 generic: backport upstream leds-st1202 fixes
Backport 12 upstream fixes for the ST LED1202 driver to backport-6.12:

  894-01  leds: st1202: Check for error code from devm_mutex_init() call
  894-02  leds: st1202: Refactor st1202_led_set() to use !! operator for
          boolean conversion
  894-03  leds: leds-st1202: Initialize hardware before DT node child
          operations
  894-04  leds: leds-st1202: Spacing and proofreading editing
  894-05  leds: st1202: Stop pattern sequence before reprogramming
  894-06  leds: st1202: Validate pattern input before stopping the
          sequence
  894-07  leds: st1202: Fix pattern duration prescaler and
          pattern_clear skip marker
  894-08  leds: st1202: Set all pattern PWM slots to full after
          clearing pattern
  894-09  leds: st1202: Fix spurious pattern sequence start in setup
  894-10  leds: st1202: Fix brightness having no effect while pattern
          mode is active
  894-11  leds: st1202: Disable channel when brightness is set to zero
  894-12  leds: st1202: Validate LED reg property against channel count

894-01 through 894-04 landed in v6.15; 894-05 through 894-12 were
merged for v7.3 and are now also in stable 6.18.52 and 6.18.53, so
none of these are needed for backport-6.18.

Assisted-by: LLM
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23455
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:43:09 +02:00
Julius Bairaktaris 9708be59b2 pcre2: enable JIT on riscv64 and loongarch64
PCRE2 supports JIT on RISC-V and LoongArch64, but PCRE2_JIT_ENABLED
cannot be selected for them. Allow it and enable it by default, as on
aarch64.

libpcre2-8.so grows by 61 KiB on riscv64 and 54 KiB on loongarch64,
compressed with xz.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25582
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:39:40 +02:00
Ivan Pavlov 5c46468a1c pcre2: update to 10.49
Changelog: https://github.com/PCRE2Project/pcre2/blob/main/ChangeLog

Signed-off-by: Ivan Pavlov <AuthorReflex@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25562
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:37:03 +02:00
Yangyu Chen 547dee4729 openssl: optimize speed for riscv64 by default
RISC-V is becoming more popular, and it's beneficial to have OpenSSL
optimized for speed on riscv64 architectures by default. And many
algorithms in OpenSSL currently lack assembly optimizations for riscv64,
so optimizing for speed for riscv64 will bring significant performance
improvements for C implementations. For example, the performance of
ChaCha20 improves dramatically with this change, from 63603.67k to
129428.12k on Bananapi BPI-RV2 with rva22u64 profile.

All existing boards that use riscv64 that support boot from SDCard or at
least 128M NAND flash, so the slight increase in binary size is
acceptable. And I have tested this change to build with even rva22u64
profile, the libssl.so.3 only increases from 972K to 1.1M, which is
acceptable for most use cases.

Signed-off-by: Yangyu Chen <cyy@cyyself.name>
Link: https://github.com/openwrt/openwrt/pull/21070
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-04 11:23:11 +02:00
Gennaro Cimmino 416e4e7ea3 realtek: l3: trap IPv4 routes until their gateway answers
An IPv4 route through a switch port got its entry only when its gateway
resolved, and a route with no gateway - a connected prefix - never got
one. Until then, or for good, a shorter prefix in hardware forwarded
its destinations through another gateway: a /24 under an offloaded /16
whose gateway is slow to answer or gone, or a host of a connected /24
under it that has not been resolved yet.

Give these routes their entry when they are added, trapping to the
CPU, which resolves the gateway or the host. otto_l3_route_update_hw()
turns a gateway's entry into a forwarding one once it answers, at the
row the route already holds. IPv6 routes do the same since they were
offloaded.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
against the tree without this change, with the same /16 and echoes as
the previous commit:
- a /24 and a /32 through a gateway that never answers, and a
  connected /24 with no host on it: before, no entry, and all 5
  echoes reach the /16's gateway; now a trap entry, and none do.
- a /24 and a /32 through a gateway that answers still end up
  forwarding, and all 5 echoes reach that gateway; a blackhole /24
  replaced by such a route leaves one forwarding row.
No entry is left after the deletes.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25572
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:19:34 +02:00
Gennaro Cimmino 3b0479f6b4 realtek: l3: trap IPv4 routes left out of the offload
A route the driver leaves out is the CPU's to forward, but a shorter
prefix in hardware still matches its destinations and forwards them
through its own gateway. IPv6 routes left out get a row that traps;
IPv4 ones got one only at /32, and only when they had no device, so a
blackhole, unreachable or prohibit /24 under an offloaded /16, or a
/24 through a device outside the switch, went the /16's way. So did
an address of the box on such a device - a loopback or a WAN address
under an offloaded prefix.

Give every IPv4 route left out an entry that traps: a /32 in the host
table as before, anything shorter a row of its own, the default route
none since the catch-all row already traps what nothing else matches.
The entry is keyed on no gateway, so the delete handler takes it out
by destination before it looks for the route's gateway.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
against the tree without this change. 10.99.0.0/16 through a gateway
on a switch port, in hardware, and 5 echoes from a host on another
VLAN into each route below:
- a blackhole /24, a prohibit /24 and a /24 through a bridge without
  ports: before, no entry, and all 5 echoes reach the /16's gateway;
  now a trap row, and none do.
- a /32 address of the switch on that bridge: before, all 5 reach the
  /16's gateway and none is answered; now the switch answers all 5.
No entry is left after the deletes. A build without the delete
handler's part leaves the trap row of the /24 through the bridge
behind once its route is gone.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25572
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:19:34 +02:00
Gennaro Cimmino 7e1acbc0e8 realtek: l3: start over when the FIB dump is inconsistent
register_fib_notifier() replays the FIB to the notifier before it starts
delivering events, and checks that nothing changed while it did. When
something did, it unregisters the notifier, calls the callback it was
given and dumps again, up to five times. The driver passed no callback,
so a route the first dump queued and the FIB lost before the next one
stayed programmed for good: its delete went to no one.

Pass a callback that takes out every route the driver programmed,
after the work the dump queued has run. The catch-all rows stay: no
table owns them.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
through a bench-only debugfs file that unregisters the notifier, takes
out the driver's routes and registers it again, as probe does, with
and without this callback. 20000 routes in table 100 make the dump
long; 40 /24s in main are deleted and added back while it runs, and
deleted at the end. Eight runs each, every one taking 2 to 5 dumps:
- without the callback, 7 of 8 runs leave 13 to 40 of those /24s in
  hardware, though the kernel has none;
- with it, none is left in any run.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25571
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:14:38 +02:00
Gennaro Cimmino ddd604afb3 realtek: l3: use the IPv6 member count taken at notify
The notifier records how many members an IPv6 route has when the event
fires, because the work that handles the event runs later. The check
that refuses multipath routes still read the route's own sibling count
at that later point. A member appended and deleted before its append
was handled has had that count cleared by then, so the append
programmed it as a single route through its own gateway, replacing the
row of the route it had joined, and the delete took that row away. The
route left behind had no row, and a shorter prefix in hardware
forwarded its traffic to another gateway.

Decide on the recorded count, on add and delete alike. The route left
behind keeps a trap row until its next event, as it already does when
the member leaves after its append was handled.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this change. fd00:9d::/32 through one gateway
and fd00:9d:N::/48 through another, both in hardware; then a single
ip -batch adds 40 filler routes, appends a second member to the /48
through the /32's gateway and deletes it again. The fillers keep the
work queue busy, so the append is handled after the delete: a marker
written to the kernel log right after the batch precedes the driver's
check of the append in 5 of 5 runs on both images.
- main: the /48 is left without a row, and all 5 echoes sent into it
  reach the /32's gateway, in every run.
- this change: the /48 keeps a trap row, and the 5 echoes reach its
  own gateway through the CPU, in every run.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25564
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:07:00 +02:00
Gennaro Cimmino 89b1b06094 realtek: l3: do not offload routes with a tunnel
A route can carry a lightweight tunnel - seg6 encapsulation, an MPLS
label push - that the kernel applies to every packet it forwards. The
FIB notifier never looked at it, so such a route through a gateway on
a switch port was offloaded like any other, and the hardware forwarded
its traffic to the gateway bare. OpenWrt enables seg6 lightweight
tunnels by default on every target without small_flash, realtek
included.

Leave these routes out, on both families. An IPv6 one gets a trap row,
as the other IPv6 routes the driver leaves out do. An IPv4 one takes
the path of the routes without a device or through a nexthop object:
a /32 is trapped in the host table and a shorter prefix gets no row,
so an offloaded shorter prefix covering it would still forward its
traffic. The delete handler takes the same path, so a trapped /32 does
not outlive its route.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this change. Three routes with seg6
encapsulation through a gateway on a switch port - 10.99.80.0/24,
10.99.81.7/32 and fd00:9a::/48 - each took 5 echoes from another VLAN.
- main: each gets a forwarding row, and the gateway receives all 5
  echoes bare, none encapsulated.
- this change: no row for the /24, a trap row for the /32 and the
  /48, and the gateway receives none bare and all 5 inside an IPv6
  segment routing header. No row is left after the deletes.
A build without the delete half leaves the trapped /32 in the host
table once its route is gone. An IPv4 and an IPv6 prefix without a
tunnel, through the same gateway, forward in hardware on both images,
5 of 5.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25560
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:05:14 +02:00
Rustam Adilov d30a4dfd42 realtek: add support for RTL9607C Serdes MDIO bus
RTL9607C has 3 SerDes starting at 0xbb040030. Serdes 0 is for PON transceiver
and Serdes 1/2 are HSGMII. The pages are laid out in a similar structure as
RTL838x with SDS, SDS_EXT, FIB, FIB_EXT but not in the same order as the rest
of the switch SoCs: WSDS_DIG is 1st, then goes WDIG, ANA_MISC, ANA_COM, ANA_SPD
ANA_1P25, ANA_GPON, ANA_EPON, and then ordinary SDS, SDS_EXT, FIB and FIB_EXT.
The serdes 1/2 however only have WSDS_DIG, SDS, SDS_EXT, FIB and FIB_EXT pages.

RTL9607C has a WSDS_DIG page which seems a bit different from WDIG so add it to
rtsds_page_name struct.

There is however another page WSDS_ANA that comes before WSDS_DIG at 0xbb040000
but it is ignored because it doesn't align nicely, is empty with full of DMY
bit fields and is unused by SDK anyway.

Signed-off-by: Rustam Adilov <adilov@tutamail.com>
Link: https://github.com/openwrt/openwrt/pull/25463
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-04 09:02:07 +02:00
Ivan Pavlov 5edcc1c43c openssl: update to 3.5.9
Is a security patch release.  The most severe CVE fixed
in this release is High.

This release incorporates the following bug fixes and mitigations:

  * Fixed DTLS retransmissions of handshake messages from a stale buffer offset.
    ([CVE-2026-84782])

  * Fixed excessive memory allocation in relative CRLDP processing.
    ([CVE-2026-35189])

  * Fixed QUIC unvalidated amplification credit may be over-accounted.
    ([CVE-2026-35191])

  * Fixed potential CPU DoS via O(n^2) fragment reassembly in QUIC.
    ([CVE-2026-42772])

  * Fixed a timing side-channel in scalar multiplication for mon-NIST EC curves.
    ([CVE-2026-54872])

  * Fixed QUIC `STREAM` fragment metadata DoS.
    ([CVE-2026-54873])

  * Fixed non-constant-time SM2 scalar multiplication on ARM64 and RISC-V.
    ([CVE-2026-54875])

  * Fixed out-of-bounds access after `SSL_set_SSL_CTX()` during a handshake.
    ([CVE-2026-72897])

  * Fixed QUIC connection-level flow control was not enforced for streams.
    ([CVE-2026-75804])

  * Fixed a NULL pointer dereference in CMP client revocation response handling.
    ([CVE-2026-75805])

  * Fixed an unauthenticated and undersized DTLS 1.2 AEAD record causing DoS.
    ([CVE-2026-75806])

  * Fixed a timing side-channel in SM2 signature generation.
    ([CVE-2026-77696])

  * Fixed an unbounded `RETIRE_CONNECTION_ID` backlog in QUIC stack
    implementation.
    ([CVE-2026-84784])

  * Fixed a bug where `EVP_DecryptFinal()` incorrectly reported a stale success
    on AES-SIV authentication failure.

Signed-off-by: Ivan Pavlov <AuthorReflex@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25557
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-04 02:12:00 +02:00
Paul Spooren 1eaea67aef tools/mtd-utils: make mkfs.ubifs images reproducible
UBIFS root file systems differ between builds, e.g. the one of the
Microchip SAMA7G5-EK: the superblock gets a random UUID, the inodes get
the ctime of the build host, which can't be reset with touch, and the
entries of each directory are added in readdir() order, which depends on
the host file system and decides inode numbers and layout.

Add a patch that, when SOURCE_DATE_EPOCH is set, uses a time-based
(version 1) UUID with that time and clamps all inode times to it. The
node ID of the UUID is taken from the new --uuid-node option, which the
image build sets from IMG_PART_DISKGUID, itself derived from
SOURCE_DATE_EPOCH and the kernel vermagic.
Directory entries are added sorted by name. Two trees with the same
contents but different ctimes and readdir() order now give identical
images; without SOURCE_DATE_EPOCH the UUID stays random.

Link: https://github.com/openwrt/openwrt/pull/25430
Signed-off-by: Paul Spooren <mail@aparcar.org>
2026-10-03 22:45:10 +02:00
Shiji Yang 6bfbb7ef9d wireless-regdb: update to version 2026.09.03
Git commit changes:
389b9b7 wireless-regdb: update regulatory database based on preceding changes
8f1e802 wireless-regdb: allow 320MHz channel width for Hong Kong (HK)
74cb99f wireless-regdb: Update 2.4 and 5 GHz rules for South Africa (ZA)
2482838 wireless-regdb: Remove DFS flag from 60 GHz band for Togo (TG)

Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/25008
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2026-10-03 22:22:41 +02:00
Gennaro Cimmino c9fb1ff937 realtek: l3: tear down a replaced IPv4 route first
Deleting the route the kernel selected for an IPv4 prefix does not
always notify a delete. When another route for the same prefix and
table remains, fib_notify_alias_delete() sends a replace carrying that
successor instead. otto_l3_fib_add_v4() looked up the switch port of
the new route before taking out the programmed one, so a successor
through a device outside the switch - a WireGuard tunnel, say -
returned -ENODEV and left the old row forwarding to a gateway the
kernel no longer uses. The delete of the successor finds no row of
its own, so the stale one outlives both routes.

Take the programmed route out before anything can turn the new one
down, as the IPv6 path already does. The successor still gets no row,
so a shorter prefix in hardware would forward its traffic, as it does
today for any IPv4 route through a device outside the switch.

Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
main against main with this change. 10.99.70.0/24 via a host behind a
switch port, metric 10, then the same prefix via a bridge without
ports, metric 20, then the metric 10 route deleted. On both images the
kernel keeps the bridge route and the driver logs "lower interface
wanx not found".
- main: the row stays forwarding, 5 of 5 echoes sent to the prefix
  reach the old gateway, and the row outlives both routes.
- this change: no row, 0 of 5 echoes reach the old gateway.
With the successor behind a switch port instead, both images end with
one forwarding row and its gateway receives 5 of 5 echoes.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25559
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 21:21:49 +02:00
Paul Spooren e77f27eda8 gemini: make the DNS-313 factory image reproducible
The boot partition of the DNS-313 factory image differs between builds:

  -Linux rev 1.0 ext2 filesystem data, UUID=9f7d7721-0bf7-4483-bd56-b539d195f181
  +Linux rev 1.0 ext2 filesystem data, UUID=d3ca4870-378b-48dd-9b05-760812dfeb81
  -drwxr-xr-x ... 2026-09-23 07:37:23.000000 ./.boot/
  +drwxr-xr-x ... 2026-09-23 09:38:09.000000 ./.boot/

genext2fs copies the mtimes of the staged files from the host and adds
them in readdir() order, which also decides their inode numbers and
blocks. It leaves the UUID empty, so e2fsck fills in a random one, and
e2fsck stamps the last check with the current time.

Pass genext2fs a name sorted tarball with mtimes clamped to
SOURCE_DATE_EPOCH and group/other write bits cleared, derive the UUID
from IMG_PART_DISKGUID and run e2fsck with E2FSCK_TIME set to
SOURCE_DATE_EPOCH.

Link: https://github.com/openwrt/openwrt/pull/25358
Signed-off-by: Paul Spooren <mail@aparcar.org>
2026-10-03 20:56:05 +02:00
Paul Spooren ab8d38d99b restool: sort source files for reproducible builds
Right now the list is generated by find, which order depends of the underlying
filesystem. This causes reproducibility issues within the OpenWrt build system.

Fix it by adding a deterministic sort.

Sent to upstream via https://github.com/nxp-qoriq/restool/pull/3

Link: https://github.com/openwrt/openwrt/pull/25531
Signed-off-by: Paul Spooren <mail@aparcar.org>
2026-10-03 20:22:20 +02:00
Eduard Hart a20047f6ee qualcommax: add support for TP-Link RE700X
TP-Link RE700X is a dual-band Wi-Fi 6 (AX3000) range extender based on
Qualcomm IPQ5018 (2.4 GHz) with a QCN6122 (5 GHz) companion radio.

Specifications:
- SoC: Qualcomm IPQ5018 (dual-core ARM Cortex-A53)
- RAM: 256 MiB
- Flash: 128 MiB SPI-NAND (ESMT F50D1G41LB)
- Wi-Fi: IPQ5018 2.4 GHz + QCN6122 5 GHz, both 802.11ax
- Ethernet: 1x Gigabit - IPQ5018 MAC1 (DWMAC) via SGMII/uniphy0 to a
  Realtek RTL8211F (MDIO1 addr 6). The SoC internal GE PHY (MAC0/gmac0)
  is not wired to any external port and stays disabled.
- LEDs: 5, Buttons: reset + WPS
- Power: 100-240 V AC, 50/60 Hz, 0.4 A (internal PSU, wall-plug)
- UART: 3.3 V serial console, 115200 8N1; on-board 4-pad header,
  pinout from top: TX, RX, GND, VCC

MAC addresses (factory_data UBI volume, file default-mac, mounted
read-only in preinit like on the EAP650):
- LAN (label MAC): default-mac
- 2.4 GHz: default-mac + 1
- 5 GHz: default-mac + 2

Calibration data is extracted from the 0:art partition (IPQ5018 at
0x1000, QCN6122 at 0x26800).

Installation:
- From OpenWrt (or after a RAM-boot of the initramfs via U-Boot/TFTP):
  sysupgrade.
- From the stock firmware: openwrt-...-squashfs-factory-webflash.bin via
  the TP-Link web UI (System -> Firmware Upgrade).
  scripts/tplink-re700x-factory.py wraps the rootfs UBI into the stock
  "nvrammanager" upload container (the same "tplink2022"/safeloader
  family as scripts/tplink-mkimage-2022.py); the stock flasher writes it
  into the inactive dual-boot slot. This path has not been tested end to
  end (no unit on stock firmware was left), so keep UART at hand for a
  first install.

The stock U-Boot passes a slot-correct ubi.mtd= (rootfs / rootfs_1 per the
dual-boot index) but with an unmountable root=mtd:ubi_rootfs. The DTS /chosen
inherits ubi.mtd= and appends root=/dev/ubiblock0_1, so OpenWrt boots from
whichever slot the flasher wrote. Like on the EAP650, sysupgrade installs
into the inactive slot and then points tp_boot_idx at it, keeping the
running slot as a fallback; the U-Boot environment is on 0:appsblenv.

The QCN6122/IPQ5018 board-2.bin (BDF) data is supplied via
ipq-wifi-tplink_re700x (openwrt/firmware_qca-wireless).

Wi-Fi is disabled in the DTS for now: with the default ath11k DP ring
sizes both radios exhaust the 256 MiB of RAM. It will be enabled in a
follow-up together with the ath11k patch that selects smaller rings on
low-memory boards, once that has been accepted upstream.

Signed-off-by: Eduard Hart <eduard.hart@etik.com>
Link: https://github.com/openwrt/openwrt/pull/23982
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-03 20:17:43 +02:00
Markus Stockhausen 4dbdfecf0c realtek: dsa: move defines out of rtl-otto.h
Move register definitions and constants to the functional source files
and headers that use them. Keep private definitions in their translation
units and shared definitions in the corresponding headers.

Remove unused defines, preserve associated comments and collapse
consecutive blank lines. Adjust includes and move rtldsa_flood_type to
l2.h to avoid circular header dependencies.

Macro values and runtime behavior remain unchanged.

Assisted-by: ChatGPT (OpenAI GPT-6.1 Sol)
Link: https://github.com/openwrt/openwrt/pull/25550
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 19:13:32 +02:00
Gennaro Cimmino 0d212bc523 realtek: l3: offload only main and local table routes
The switch has a single routing table. The driver tells its routes apart
by the kernel table they came from, but writes every one of them to that
single table, where it matches whatever packet the hardware routes. A
route that only a policy rule selects - one per uplink, the way
multi-WAN setups do it - is then applied to all traffic, and two routes
to one prefix from two tables become two rows for the same destination,
either of which can answer.

Take FIB events from the main and local tables only, for both address
families, and warn about a route from any other: it stays in software.
The local table carries the switch's own addresses, which the driver
traps. A route from another table is set aside before anything else
looks at it, so an IPv4 route there with an IPv6 gateway is no longer
refused.

This is a change for IPv4 as well, which has had the same exposure: a
route in another table was offloaded until now. The RTL839x, whose L3
code runs in a stock build, is affected the same way and was not
tested.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 15:34:36 +02:00
Gennaro Cimmino 7abc4c6404 realtek: l3: rtl930x: trap what no IPv4 row matches either
The drop a missed route lookup ends in does not care which family asked,
and neither does the router MAC that feeds it: an IPv4 destination with
no row of its own is dropped in silicon exactly as an IPv6 one was. An
IPv4 connected route reaches the handler, is given a route object and
has the kernel told it is offloaded, and never has a row written for it,
so every host on-link behind this switch is one of those destinations.

Give that family the same last row, from the same helper. It differs
only in which end of the table the block grows from, which the placement
already knows.

This sits here rather than on its own because the row it needs is a row
the table can hold: before the entries were ordered by prefix length a
prefix route lived at the row its id happened to be, and a catch-all
would have had to pin one. The ordering arrived with the IPv6 work, and
with it this became a second call to a function that was already there.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 15:34:36 +02:00
Gennaro Cimmino 5bcc08cdd5 realtek: l3: rtl930x: trap what no row matches
The router MAC this driver installs matches on any port and any VLAN, so
from the first offloaded route every IP frame addressed to the switch is
pulled into the route lookup. A destination the driver did not program
misses that lookup, and a miss is a drop: not a trap, not a punt to the
CPU, a drop in silicon before anything upstream can see the packet.

A route with no gateway to resolve is never offloaded, so every on-link
prefix is such a destination. Measured on an RTL9303 with two bridge
VLANs, one port each, an address of the switch on both, routing on and
the firewall stopped:

	from VLAN 10 to the switch, same VLAN		20/20
	from VLAN 10 to the switch, in VLAN 20		20/20
	from VLAN 10 to a host on-link in VLAN 20	 0/20

The middle line is the control: crossing VLANs works, and it works
because that destination has a row. The third has none, and the drop
counter follows the packets: against an idle span of the same length
that read four, the twenty-packet arm read twenty-four
IPUC_ROUTING_LOOKUP_MISS, while a deliberate VLAN violation over the
same two ports raises VLAN_IGR_FILTER and leaves that counter at zero.

The arms are IPv4 because the miss does not depend on the family: the
router MAC is matched before the lookup and the lookup is what fails.
So the offload makes the switch worse at forwarding than it is with the
offload off, which is a regression and not a missing feature.

The miss itself cannot be steered. The Realtek GPL SDK carries a lookup
miss action in the multicast route controls and in neither of the
unicast ones - rtk_longan_regField_list.c gives L3_IPMC_ROUTE_CTRL and
L3_IP6MC_ROUTE_CTRL a LU_MIS_ACT field and gives the two unicast
registers none. What a unicast row can carry is an action of its own,
and trapping is one of them.

Write that row. One entry, prefix length zero, the trap action and no
next hop, at the end of the block: the rows are ordered longest prefix
first and the hardware answers with the lowest matching row, so every
destination that has a row of its own is answered by it and only what
nothing matches arrives here. What arrives is handed to the CPU, which
is where it would have gone with the offload off.

It costs one of the 127 entries the table holds for IPv6 and it costs
that traffic the hardware path, which it never had. The row is written
where the tables are set up, before the notifiers are registered, so
there is no window in which the tables are live and a destination is
dropped for want of a route that has not arrived yet.

Only a switch whose L3 tables carry the destination writes it, which is
an RTL930x built with the offload symbol, and no subtarget config sets
that. The RTL839x reaches none of this.

This commit writes the IPv6 row only, so the IPv4 arms above are still
answered the same way at this point in the series: the row that answers
them is in the commit after this one.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 15:34:36 +02:00
Gennaro Cimmino 666ac0c2c5 realtek: l3: rtl930x: widen the dump for IPv6 destinations
The destination column is 24 characters wide, which fits an IPv4 address
and its prefix length with room to spare and an IPv6 one only when it
compresses well. The link-local rows this driver writes take up to 29
characters, an address with nothing to compress takes 43, and the column
they run into is the action, so the two print as one word.

Widen the column, and give the buffer the width the kernel uses for an
address it prints: %pI6c writes a dotted quad for the v4-mapped and
ISATAP forms, which reach 44 characters, and 48 held those but not the
prefix length after them.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 15:34:36 +02:00
Gennaro Cimmino 99b56c4deb realtek: l3: rtl930x: offload IPv6 unicast routes
The IPv6 half of the L3 tables is written and read by the same code that
drives the IPv4 half, and the setup enables it in hardware, but nothing
has ever produced a route for it: the FIB notifier dropped every IPv6
entry event and the handler behind it was a stub.

Take those events, hold the route across the work item that handles
them, and program the prefix table from them the way the IPv4 handler
does, minus the host route table: the prefix entry carries a host-route
bit of its own, which the writer already sets for a prefix length of
128, so one table serves every prefix length.

Offloading is refused for a nexthop object, a source-specific route, a
multipath route, anything that is not plain unicast, a route with no
gateway, and the two destinations no forwarding row should match: the
default route, which would take everything, and the loopback address.

Refused is not the same as left alone. A shorter prefix that is
offloaded still matches such a destination and forwards it, whatever the
route says: a blackhole /64 under an offloaded /48 would be forwarded to
the /48's gateway. So a refused route gets a row of its own that traps
to the CPU, which routes it as the kernel does. The default route gets
none, since that row would match every destination; the catch-all row
added later in this series traps what no other row matches. A multicast
route gets nothing either. A delete takes that row out before anything
else, since the route it belonged to was never judged offloadable. The
cost is an entry per such route; on the bench, the connected prefixes,
fe80::/64 and the ULA prefix netifd adds as unreachable, five entries in
all. A multipath route keeps its row until its last member is gone: an
add carries the route with every sibling it has, a delete names only the
members that leave, so the row counts them. Source-specific routes to
one prefix share its row, which counts the members of the last one to
arrive, so deleting one can take the row from the others; the driver
logs an error for every source-specific route it traps.

An add arrives as a replace even when it is the only word the kernel
sends about a programmed route going away, so the row for a destination
is taken out before the route replacing it is judged, and a delete is
matched on its gateway as well, because entries that share a destination
arrive with their sibling count already cleared. A multipath route that
shrinks back to a single one stays refused until something touches it
again: the only word about it names the member that left.

A route takes its row as soon as it is added, as a trap: until its
gateway answers, a shorter prefix in hardware would otherwise forward
what this route has yet to resolve. It holds the FIB entry it came from
until the row goes, and is reported as trapping until the gateway
answers and the row forwards, then as offloaded; one that finds no free
row is reported as failed. One whose gateway answered on no port the
switch knows keeps trapping, so it is reported as trapping, not
offloaded, until an update gives it a port. So is one whose gateway's
neighbour stops being valid, until it is valid again.

That leaves the switch's own addresses. A packet whose destination MAC
is the switch's own terminates on the router MAC table and is then
looked up as a route, and that table carries no IP address, so the
hardware has no notion of which addresses are its own: such a packet
misses the lookup and is dropped. The IPv4 path mostly escapes this,
because it writes a host route trapping each of its own addresses that
sits on a device with a switch port below it, and because ARP is not IP
and the setup traps non-IP traffic separately. Neighbour discovery is
ICMPv6, so IPv6 has neither.

What a neighbour sends to a multicast address is untouched, never
carrying the switch's MAC, so a gateway is still learned from an
unsolicited advertisement. Every unicast step after that is not: the
solicitation addressed to the switch, and the reachability probe that
follows, both carry its MAC and both die in the lookup, so the
neighbour ends up FAILED all the same.

So give every local IPv6 address a prefix route of its own that traps to
the CPU, which is how the SDK asks for one - an entry with no next hop
and the trap action. On a device with forwarding on, the kernel also
joins the subnet-router anycast address of every prefix shorter than a
/127 whose network part is not all zeroes, link-local ones included,
and names its route RTN_ANYCAST rather than RTN_LOCAL; that address is
the switch's as much as the others, so it is trapped with them.

Measured on an RTL9303 with the offload built in, which no subtarget
config does: the switch answers on its own address and on that anycast,
five of five each, and the anycast row comes back with its hit bit set.
With fd00:99::/48 offloaded and fd00:99:0:1::/64 a blackhole, the /64
gets a trap row and pings into it no longer reach the /48's gateway, 0
of 5, while the rest of the /48 still does, 5 of 5; with the blackhole
deleted, its row goes and the same pings arrive, 5 of 5. A /64 through a
gateway that never answers, under such a /48, has its trap row from the
moment it is added: none of five pings reaches the /48's gateway and the
sender is told the address is unreachable, where without that row the
/48 forwarded all five. A multipath /48 under an offloaded /32 keeps its
trap row when one member is deleted, so its traffic follows the member
left, five pings of five, instead of the /32's gateway; and an address
that becomes the switch's own where a route through a gateway held it
gets its trap row, and the switch answers on it.

An address the box holds on several devices at once reaches the driver
once, for whichever of them the kernel made the leaf of that
destination: a bridge, its VLAN interfaces and the conduit all carry the
same link-local, and the one that wins need not be a switch port. So
which device holds an address says nothing about whether it has to be
trapped, and none of them is asked. While a copy remains the kernel
replaces the entry rather than deleting it, so the row is written once
and removed when the last copy goes. An address arrives before the
replace that takes out a route already holding its destination, so only
a row that traps is kept; any other row there is taken out first. Each
row costs one of the 127 slots the table has for an IPv6 entry, taken
from the end the IPv4 rows grow towards; an address that finds none is
left without a row, which makes it unreachable from the switch ports,
and dmesg is the only sign of it.

Telling a row from another takes the next hop index it carries: the id
of the route that wrote it once its gateway answered, and zero on a row
that only traps. So the test that says whether a row is still the route
being removed now compares the action as well, and the index with the
one the route itself wrote rather than with its id - on the removal path
both address families share.

The per-event warning the notifier used to print for an IPv6 entry goes
with the branch that printed it.

Everything IPv6-specific sits behind IS_REACHABLE(CONFIG_IPV6): the FIB
event branch, the FIB entry a route holds and its report. A kernel with
CONFIG_IPV6=n builds and links, and never sees an IPv6 route.

Driver removal gains a wait on the work queue and a pass over the route
list that releases the FIB entries still held. otto_l3_remove() is on
the unbind path of every family, so both run there: the pass finds
nothing to release where no route ever held an entry, and the wait is
for work that family queues on the same single-threaded queue.

Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 15:34:36 +02:00
Robert Marko dfb281ad5e apboot-aruba-ipq806x: make timestamps reproducible
APBoot embeds the current time in both its version banner and generated
U-Boot timestamp header. This makes the AP-32x bootloader artifact
differ between otherwise identical builds.

Use SOURCE_DATE_EPOCH for these timestamps when it is set, while
retaining the wall-clock fallback for other builds.

Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-03 12:15:18 +02:00
Robert Marko fcc5cb880e image: make kernel UBIFS images reproducible
The temporary directory used to create a kernel UBIFS image and its
kernel file receive wall-clock mtimes. mkfs.ubifs preserves these
times, making images differ between builds.

Set their timestamps to SOURCE_DATE_EPOCH before invoking mkfs.ubifs.

Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-03 11:53:09 +02:00
Julius Bairaktaris 3bab3a63a1 mac80211: reset the LED state when ifup fails
Backport upstream commit 78183e833195 ("wifi: mac80211: reset the LED
state when ifup fails"). When the first interface fails to come up, the
throughput LED timer keeps running, and unloading the driver afterwards
frees it while it is still armed.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25539
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-03 11:47:13 +02:00
Gleb Pesin f5474890d2 ncurses: suppress line markers in generated macro wrappers
With ccache enabled, MKlib_gen.sh treats ccache as the compiler when
probing its version. It therefore misses GCC's required -P workaround
for line markers introduced while expanding macros. The generated
lib_gen.c then fails to compile with GCC 14.4.0, reporting:

  "_Bool" after # is not a positive integer

Pass -P explicitly to the make-time preprocessor used by the ncurses
source generators. This fixes the apm821xx/nand and qoriq/generic
external-toolchain CI failures without changing compiler detection
or the source library API. Increment the package release.

Build-tested complete static/shared ncurses, menu, form and panel
libraries with ccache and the failing PowerPC GCC 14.4.0 toolchains.
The same build also passes with MIPS32 GCC 16.2.0. The original
make-time CPP command reproduces both PowerPC failures.

Signed-off-by: Gleb Pesin <dormancygrace@gmail.com>
Assisted-by: Codex (OpenAI GPT-6)
Link: https://github.com/openwrt/openwrt/pull/25538
Signed-off-by: Robert Marko <robimarko@gmail.com>
2026-10-03 11:41:51 +02:00
John Crispin 5d5ade6d16 kernel: configure the kernel again after an initramfs build
Kernel/SetInitramfs writes the initramfs configuration into the kernel
tree and deletes .config.prev, so that the next configure stage puts the
regular configuration back. The check that decides if the configure stage
must run ignored this signal. The next build then compiled the regular
kernel with the initramfs configuration, and the squashfs images got a
kernel with an embedded root filesystem.

Run the configure stage if .config.prev is missing.

Fixes: e97e3f36bd ("kernel: configure the kernel only when an input changed")
Signed-off-by: John Crispin <john@phrozen.org>
2026-10-03 10:07:19 +02:00
Paul Tobias 4be0395b9e realtek: eth: drop the receive offload mark DSA overwrites
dsa_switch_rcv() sets skb->offload_fwd_mark for every frame that
arrives with hardware port metadata, from the trapped flag and the
port's bridge membership, so the mark the driver sets never survives.

Signed-off-by: Paul Tobias <openwrt-commits@tobias.pt>
Link: https://github.com/openwrt/openwrt/pull/25483
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 10:02:26 +02:00
Paul Tobias 896047f4a6 realtek: eth: rtl838x: treat RMA frames as trapped
The switch traps frames to reserved multicast addresses, BPDUs and
LLDP among them, to the CPU with reason 2 (RMA) and does not forward
them itself, but rteth_838x_decode_tag() reports them as forwarded in
hardware. RTL839x already treats its RMA reasons as trapped.

Signed-off-by: Paul Tobias <openwrt-commits@tobias.pt>
Link: https://github.com/openwrt/openwrt/pull/25483
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 10:02:26 +02:00
Paul Tobias afc936d223 realtek: eth: don't mark trapped frames as forwarded
The bridge does not forward the frames the switch traps to the CPU,
although decode_tag() reports them as not offloaded: IGMP and MLD
reports do not leave the switch, and BPDUs are not passed on while
spanning tree is off.

Give the DSA hardware port metadata a trapped flag and hand trapped
frames to the DSA core with a metadata_dst that carries it.

Fixes: e59484b39e ("realtek: dsa/eth: adapt receive path")
Signed-off-by: Paul Tobias <openwrt-commits@tobias.pt>
Link: https://github.com/openwrt/openwrt/pull/25483
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-03 10:02:26 +02:00
Markus Stockhausen 9b95be917b realtek: dsa: move MIB definitions to stats.c
Move the RTL838x, RTL839x, RTL930x and RTL931x MIB tables and
descriptors from the chip-specific files to stats.c, alongside
the code that consumes them.

Make the MIB lists static and move their initializer macros to
stats.c. Declare the descriptors in stats.h so the chip-specific
register structures can continue to reference them.

No functional change intended.

Assisted-by: ChatGPT (OpenAI GPT-6.1 Sol)
Link: https://github.com/openwrt/openwrt/pull/25545
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-02 22:06:33 +02:00
Gennaro Cimmino 2a7e6cc890 realtek: l3: rtl930x: skip the rows behind a prefix entry
An IPv6 prefix entry is matched over three consecutive rows, and the two
behind the one it is written at read back through the table access
register as valid entries of their own. The dump prints them as routes
nobody added, and the sweep that clears the hit bits does a
read-modify-write on any of them whose hit bit reads set, putting that
content into rows the allocator has already handed out.

Both walk the table one row at a time, although the decoder they call
already knows the width of what it decoded - it is what the host side
steps by. Hand them that width and step by it.

The hardware does not answer with the rows behind an entry. They sit
below it and a lookup answers with the lowest matching row, so a ::/0
there would have taken every packet the entry above it was there to
forward; measured on an RTL9303 with a /64 offloaded through a gateway,
200 packets of 200 went through that entry. What rows left behind by a
deletion do is a separate question, and the removal path rather than
this walk is where to ask it.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25540
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
2026-10-02 22:02:41 +02:00