Skip to content

Stuff - #287

Merged
ManupaKDU merged 856 commits into
Zektopic:mainfrom
openwrt:main
Oct 4, 2026
Merged

Stuff#287
ManupaKDU merged 856 commits into
Zektopic:mainfrom
openwrt:main

Conversation

@manupawickramasinghe

Copy link
Copy Markdown
Member

Thanks for your contribution to OpenWrt!

To help keep the codebase consistent and readable,
and to help people review your contribution,
we ask you to follow the rules you find in the wiki at this link
https://openwrt.org/submitting-patches

Please remove this message before posting the pull request.

hauke and others added 30 commits September 24, 2026 21:20
apup_process_beacon() dereferenced the return value of ap_sta_add()
without checking it. ap_sta_add() returns NULL when the station table is
full, when the allocation fails or when accounting_sta_get_id() fails,
so the following read of sta_ret->aid dereferences NULL.

The station table filling up is remotely triggerable. Beacons reach
handle_beacon() on every softmac driver, because hostapd subscribes to
them per wiphy with NL80211_CMD_REGISTER_BEACONS when it starts the AP.
An adjacent station can therefore beacon the target's SSID from
successive spoofed BSSIDs, each of which is added as an APuP peer, until
max_num_sta is reached and hostapd crashes.

CONFIG_APUP=y is set unconditionally in DRIVER_MAKEOPTS, so the code is
compiled into every wpad variant, but the call is gated on
hapd->conf->apup at runtime and wifi-scripts defaults apup to 0. Only
configurations that opt into APuP are affected.

Reported-by: JuliusBairaktaris
Fixes: e805201 ("hostapd: Add support for APuP")
Assisted-by: Claude:claude-opus-5
Link: #25242
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
apup_process_beacon() adds the peer with ap_sta_add() and only asks for
an AID with hostapd_get_aid() further down. When that fails the function
returns without undoing anything, leaving the station in hapd->sta_list
with WLAN_STA_AUTH set but with no AID, no WLAN_STA_ASSOC and no WDS
interface. The driver entry added by the preceding hostapd_sta_add() and
the hapd->num_sta reference are leaked as well.

The leftover entry is then found by the ap_get_sta() check at the top of
the function, so every later beacon from that BSSID returns early and
the peer can never be set up again until hostapd is restarted.

Release the half-initialised station with ap_free_sta(), which removes
the driver entry, cancels the inactivity timer registered by
ap_sta_add(), unlinks it from the list and drops the counters.

Fixes: e805201 ("hostapd: Add support for APuP")
Assisted-by: Claude:claude-opus-5
Link: #25242
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
The ubus notification for link measurements was added by replacing the
call to hostapd_handle_link_mesr_report() instead of adding to it, so
upstream's handler lost its only caller and is compiled out as dead
code, which the build shows as:

  src/ap/rrm.c:354:13: warning: 'hostapd_handle_link_mesr_report'
  defined but not used [-Wunused-function]

As a result nothing clears hapd->link_mesr_req_active or cancels
hostapd_link_mesr_rep_timeout_handler() when a report arrives, so a
REQ_LINK_MEASUREMENT issued over the control interface always ends in a
timeout even though the report was received, and the LINK-MSR-RESP-RX
event carrying the report is never emitted.

Call both handlers, which is how the ubus hook for beacon reports a few
lines above is wired up too.

Fixes: f6445cf ("hostapd: add ubus link-measurements notifications")
Assisted-by: Claude:claude-opus-5
Link: #25242
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
"\s" is not an escape sequence in a Perl double-quoted string, so the
pwm feature emits its select statement without the leading tab that
every other feature gets. Kconfig accepts the unindented line, but the
generated target/Config.in is inconsistent.

Fixes: f6fbc39 ("build: define PWM_SUPPORT arch feature flag")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
The atm feature has no entry in target_config_features(), so it selects
no symbol, and nothing else reads the feature list beyond the broken and
source-only filters. It has never gated anything. The kmod-ltq-atm-*
packages are unrelated name matches, pulled in through DEFAULT_PACKAGES.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
The x86 and armsr targets declare the vdi, vmdk and vhdx features, but
VDI_IMAGES, VMDK_IMAGES and VHDX_IMAGES depend on a hardcoded target
list instead, so the features select nothing and a target opting in has
to edit config/Config-images.in.

Give them USES_VDI, USES_VMDK and USES_VHDX in the same shape as the
other image formats and depend on those. The set of targets offering
each format is unchanged.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
CompileBPF calls clang with -g but without any prefix map. Stripping debug info
keeps .BTF and .BTF.ext, since libbpf needs them, and their line info carries
the absolute path of each source file. This makes BPF objects like qosify-bpf.o
depend on the build directory and breaks reproducibility:

  -/builder/shared-workdir/build/build_dir/.../qosify-bpf.c
  +/tmp/rebuilderd-openwrt.juCsuQ/src/build_dir/.../qosify-bpf.c

IREMAP_CFLAGS is not enough here: without CONFIG_REPRODUCIBLE_DEBUG_INFO it
only sets -fmacro-prefix-map, which leaves the line info alone, and it is empty
for external toolchains, which have no say over the host clang.  Unlike regular
debug info, BTF ships with the package, so always pass -ffile-prefix-map for
the build and staging directories.

Add an fremap helper next to iremap for that, and let IREMAP_STAGING_DIR and
CompileBPF share the map of the staging directory, so they cannot drift apart.

Link: #25359
Signed-off-by: Paul Spooren <mail@aparcar.org>
Use the realtek-pse-mcu kernel driver instead of realtek-poe. The MCU
is a Nuvoton M05xx using the gen1 protocol over UART at 19200 baud.

realtek-poe turns off the MCU's port mapping at startup, which reversed
the PoE port numbering and the front-panel PoE LEDs. The kernel driver
leaves the mapping alone, so both now match the front panel. The MCU
keeps this state across a warm reboot, so a unit sysupgraded from a
realtek-poe image stays reversed until its first power cycle.

Tested on a GS110TPP v1: the driver probes the MCU and its BCM59121,
and a PoE device on lan1 is powered.

Signed-off-by: Kel Modderman <kelvmod@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Link: #25298
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
Some of these GPIOs are shared between interfaces. Use a regulator to be
able to share them. Enable Kconfig options so that they work.

Backport one patch upstream so the patch applies. Rename another to
clarify it's in 7.2.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: #25296
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
RTL93xx ignores BMCR speed-selection updates while BMCR_ANENABLE is
set. The RTL931x mode setup therefore cannot reliably select 1000 Mbps
for forced 1000BASE-X before generic autonegotiation handling runs.

Move forced 1000BASE-X speed selection into the generic helper and
perform it after disabling autonegotiation. This also removes the
ineffective RTL931x-specific write.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
100BASE-X does not use in-band autonegotiation and requires BMCR to
select 100 Mbps. Extend the generic autonegotiation helper to always
disable AN for this mode and then program BMCR_SPEED100.

This ordering is required on RTL93xx, which ignores speed-selection
updates while BMCR_ANENABLE is set.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
100BASE-X uses a direct SerDes attachment and the same 1G-class PLL
configuration as 1000BASE-X on the supported hardware.

Teach the common attachment and PLL selectors about the mode. This is
preparation only; no additional SerDes advertises support yet.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
RTL930x uses the IP-driven mode setup for Base-X links and the 1G
analog configuration for SGMII and 1000BASE-X.

Route 100BASE-X through the same IP-driven and 1G analog setup paths.
Keep the mode unavailable until all RTL93xx support is in place.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
RTL931x handles 100BASE-X through its 1G fiber digital path, but the
FIB1G link detector must remain disabled at 100 Mbps.

Add 100BASE-X to the fiber setup and symbol-error handling paths. Share
the 1000BASE-X setup while selecting the appropriate FIB1G link-enable
value for each mode. Keep the mode unavailable until the shared
RTL93xx support is enabled.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
The generic, RTL930x, and RTL931x setup paths now handle 100BASE-X.
Add the RTL93xx hardware mode value and mapping, select the 1G analog
CMU page, and advertise the mode from RTL93xx SerDes instances.

This makes the prepared support available to PCS consumers.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
Phylink can only request interface modes advertised by the DSA port.
Expose 100BASE-X when the SoC MAC capabilities include MAC_100 so that
ports backed by a capable PCS can select the newly supported mode.

Keep this independent of MAC_1000FD because the 100 Mbps and 1 Gbps MAC
capabilities are reported separately.

Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
The post_config hooks finalize a powered-up SerDes and may calibrate
its receiver. Configure autonegotiation and the BMCR speed first so
finalization runs with the requested PCS state.

This is required for 100BASE-X on RTL930x. Calibrating with the default
1000 Mbps BMCR setting produced symbol errors until BMCR was switched
to 100 Mbps.

Preserve the changed result from set_autoneg across the post_config
callback so pcs_config keeps its existing return semantics.

Tested runtime mode transitions and cold boot on RTL838x, RTL930x and
RTL931x. Links came up and passed traffic in all tested modes with no
regressions observed.

Assisted-by: ChatGPT (OpenAI GPT-5.6 Sol)
Link: #25378
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
OpenWrt's custom uImage magic patch makes legacy image verification use
params.magic instead of IH_MAGIC.

mkimage initializes this field, while dumpimage leaves it zeroed. This
causes dumpimage to reject valid legacy uImages using the standard
IH_MAGIC with FDT_ERR_BADMAGIC.

Initialize dumpimage's magic to IH_MAGIC so the normal verification path
works by default. Also add -M handling matching mkimage, allowing
dumpimage to verify and extract uImages built with a custom magic.

Tested with the patched U-Boot 2026.07 host tools. Standard-magic images
list and extract correctly, custom-magic images are accepted with the
matching -M value, and are rejected without it or with an incorrect
magic. Extracted payloads were verified byte-for-byte.

Fixes: #25287
Signed-off-by: Massimo Mazzariol <mazzariol.massimo@gmail.com>
Link: #25288
Signed-off-by: Robert Marko <robimarko@gmail.com>
strtoull() can parse values wider than the 32-bit uImage magic field.
Reject values above UINT32_MAX before assigning the parsed value to
params.magic.

Signed-off-by: Massimo Mazzariol <mazzariol.massimo@gmail.com>
Link: #25288
Signed-off-by: Robert Marko <robimarko@gmail.com>
Reject custom magic values when strtoull() does not parse any
digits, in addition to values outside the 32-bit uImage magic range.

Signed-off-by: Massimo Mazzariol <mazzariol.massimo@gmail.com>
Link: #25288
Signed-off-by: Robert Marko <robimarko@gmail.com>
…maps

Add a common dtsi with macros for thermal trip levels and cooling maps that can be included in other
device trees.

The trip levels are spaced 1.25C apart with double that (2.5C) for the hysteresis, with 5C
hysteresis for the lowest trip level (65C) because it is preferable for the fan to run for longer at
low speed than to stop and start repeatedly.

In the absence of continuous proportional feedback control, tightly grouping the trip levels and
cooling maps minimises the frequency and amplitude of temperature and fan speed oscillations.

There are 36 trip levels and the cooling maps start from cooling state 1 (0-index) so cooling-levels
must have at least 37 elements. If greater increments between trip levels/cooling-levels are desired
or needed the cooling-levels can be padded with repeated values.

The THERMAL_TRIPS_COMMON and THERMAL_COOLING_MAPS_COMMON macros take one argument as the prefix to
the trip levels node labels. The prefix must be the same within a thermal zone.

Signed-off-by: Ryan Leung <untilscour@protonmail.com>
Link: #22936
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
…Wi-Fi temps

Add thermal zone for the Wi-Fi chip using the same trip levels and cooling maps as the CPU. The
kernel thermal governor will act on whichever temperature is the highest. There is only a single
heatsink and fan to cover both the SoC and Wi-Fi chip, so tracking both CPU and Wi-Fi temperatures
ensures that neither chip will overheat from low fan speed.

The trip levels are spaced 1.25C apart with double that (2.5C) for the hysteresis, with 5C
hysteresis for the lowest trip level (65C) because it is preferable for the fan to run for longer at
low speed than to stop and start repeatedly.

In the absence of continuous proportional feedback control, tightly grouping the trip levels and
cooling maps minimises the frequency and amplitude of temperature and fan speed oscillations.

The cooling states are set to increments of 5 (out of 255) from 12% to 61% and then increments of 10
from 61% to 100% with kick start speed at 15%. In comparison, the default in mt7981b.dtsi starts at
50% fan speed and leads to constant on/off cycles within a short period of time (every ~2 minutes).

Signed-off-by: Ryan Leung <untilscour@protonmail.com>
Link: #22936
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
…dev-name

Replace the label property for ethernet interface names with the property openwrt,netdev-name added
in commit d4d6c48 ("mediatek: filogic: support openwrt,netdev-name for renaming interfaces").

Signed-off-by: Ryan Leung <untilscour@protonmail.com>
Link: #22936
Signed-off-by: Jonas Jelonek <jonas@jonasjelonek.de>
Add upstream patch marking the 'gpll0_main' clock as critical on
IPQ5018 (gcc-ipq5018 driver), backported from upstream commit
33f9cb56cc28 ("clk: qcom: gcc-ipq5018: mark 'gpll0_main' clock as
critical").

During boot the APCS core clock feeding the CPUs can use GPLL0 as
its parent. On some boards (e.g. TP-Link Archer AX55 v1 using the
in-tree DTS since v6.18), the ipq-cmn-pll driver's pm_runtime_put()
call in its probe function asynchronously disables
'gcc_cmn_blk_ahb_clk', which in turn disables 'gpll0_main' as well,
hanging the system until the hardware watchdog restarts the board.

Marking gpll0_main as CLK_IS_CRITICAL fixes the underlying issue
directly in the GCC driver, making the previous workaround in
0191-clk-qcom-ipq-cmn-pll-keep-the-CMN-block-bus-clocks-enabled.patch
unnecessary. Drop that patch, as it addressed the same symptom by
keeping the CMN PLL block's bus clocks permanently enabled via a
devres-managed runtime PM reference instead of fixing the actual
critical clock.

Refresh the context in
0721-clk-gcc-ipq5018-remove-the-unsupported-clk-combinati.patch and
0723-clk-qcom-gcc-ipq5018-fix-uniphy-soft-reset-issue.patch, whose
hunks shifted by 9 lines due to the newly inserted patch.

Signed-off-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Link: #25386
Signed-off-by: Robert Marko <robimarko@gmail.com>
Kernel modules from the packages feed differ between builds on 6.18,
e.g. kmod-v4l2loopback, kmod-jool-netfilter, kmod-pf-ring and
kmod-usb-serial-dmx_usb_module:

  -/builder/shared-workdir/build/build_dir/.../linux-6.18.52/include/linux/ucopysize.h
  +/tmp/rebuilderd-openwrt.Xebb8P/src/build_dir/.../linux-6.18.52/include/linux/ucopysize.h

These packages call make -C $(LINUX_DIR) M=... without
KERNEL_MAKE_FLAGS, so they get none of the OpenWrt prefix maps. With
6.12 that did not matter, since srctree stayed "." and the kernel
headers were included by a relative path. Since 6.13 srctree holds the
absolute path of the kernel tree for external modules, while kbuild
only maps srcroot, the module directory.

Add a pending patch that maps the kernel tree for external modules too.
It is added before the map of srcroot and before KCFLAGS, and GCC uses
the last matching map, so modules built through KERNEL_MAKE_FLAGS keep
their current output.

Link: #25356
Signed-off-by: Paul Spooren <mail@aparcar.org>
Add a pending upstream patch[1] to add the reset to the SDHCI controller.
This allows it to reset itself on probe and avoids warnings due to leftover
bootloader configuration.

[1] https://patchwork.kernel.org/project/linux-arm-msm/patch/20260925191706.1579990-1-robert.marko@sartura.hr/
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
EDMA maps RX fill buffers with DMA_TO_DEVICE but unmaps them with DMA_FROM_DEVICE. Use DMA_FROM_DEVICE consistently, release mappings left on RX rings during teardown, and flush ring-disable writes before descriptor cleanup.

Signed-off-by: krava <igor.kravchenko05@gmail.com>
Link: #24218
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add missing syscall names needed on 32-bit platforms to the pre-main
pre-main syscall allowlists.

Fixes: #25392
Fixes: ee526db ("procd: update to git HEAD of 2026-09-13")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
When the TRX magic check fails, trx_fixup() jumps straight to the err
label, which only returns -1. At that point the mtd device has already
been opened and the whole partition has been mmap()ed, so both the file
descriptor and the mapping are leaked.

Add an err2 label that unwinds the mapping before falling through to the
existing close(bfd), so the error path unwinds in reverse order of
acquisition like the success path does.

Fixes: bbd9eb4 ("clean up mtd, fix up trx header when integrating jffs2 data on broadcom devices")
Assisted-by: Claude:claude-opus-5
Link: #25284
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
trx_fixup() computed the CRC32 range from the on-flash TRX header
without validating it:

    scan = ptr + offsetof(struct trx_header, flag_version);
    trx->crc32 = crc32buf(scan, trx->len - (scan - ptr));

trx->len is read from the mmap()ed partition and is only sanity checked
in trx_check(), which is a separate entry point. A trx->len larger than
the partition therefore makes crc32buf() walk that many bytes past the
end of the mapping and crash mtd with SIGSEGV.

The mirror case of a trx->len below the 12 byte offset does not overread
in practice: crc32buf() takes a size_t but passes it to crc32(), which
takes an int len and loops on "while (--len >= 0)". The wrapped value
truncates to a negative int, so the loop body never runs and a zero
length CRC32 is written instead. Values at or above 0x8000000c truncate
the same way. Only the range from sizeof(struct trx_header) to roughly
0x8000000b stays positive through the truncation and reads out of
bounds, which is exactly the range a plausible bad length falls into.

Bound trx->len on both sides before computing the range, using the same
lower limit trx_check() already applies. Both comparisons are unsigned,
so the wrapping cases are rejected as well.

trx_fixup() runs as root on the contents of the flash, so this is a
robustness fix rather than a privilege boundary: it is reachable through
"mtd jffs2write" and the jffs2_replaced path of "mtd write", not through
"mtd fixtrx", which uses mtd_fixtrx() and derives its length from
erasesize instead. The practical benefit is not crashing on a truncated
or corrupted header during sysupgrade.

Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-wch3-f5gc-mw2h
Reported-by: @tonoyx91
Reported-by: @0xROI
Fixes: bbd9eb4 ("clean up mtd, fix up trx header when integrating jffs2 data on broadcom devices")
Assisted-by: Claude:claude-opus-5
Link: #25284
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
l0rdg3x and others added 13 commits October 3, 2026 15:34
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: #25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25313
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25550
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #23982
Signed-off-by: Robert Marko <robimarko@gmail.com>
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 nxp-qoriq/restool#3

Link: #25531
Signed-off-by: Paul Spooren <mail@aparcar.org>
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: #25358
Signed-off-by: Paul Spooren <mail@aparcar.org>
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: #25559
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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: #25008
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
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: #25430
Signed-off-by: Paul Spooren <mail@aparcar.org>
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: #25557
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
@ManupaKDU
ManupaKDU merged commit e768503 into Zektopic:main Oct 4, 2026
1 check passed
ManupaKDU pushed a commit that referenced this pull request Oct 4, 2026
Integrate openwrt/openwrt at dfb281a. Resolve timestamp dependency checks with shell-free argument lists, retain streamed Belkin image generation with SOURCE_DATE_EPOCH, and preserve shell-free wireless commands.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment