gemini enables ext4 for the hard disk image of the D-Link DNS-313, so
the flash images of the DIR-685 are built for ext4 as well. The ext4
root file system is padded to CONFIG_TARGET_ROOTFS_PARTSIZE, which
makes these images about 108 MiB, while the DIR-685 has 32 MiB of
flash.
The ext4 sysupgrade image is broken anyway: the ext4 images are gzipped
as a whole, which moves the image metadata into the gzip stream, so
sysupgrade rejects it with "Image metadata not present".
Build the DIR-685 images for squashfs only, like the StorLink reference
designs.
Link: https://github.com/openwrt/openwrt/pull/25658
Signed-off-by: Paul Spooren <mail@aparcar.org>
cortexa72 enables ext4 for its eMMC and SD card devices, so the UBI
images of the MikroTik RB5009 are built for ext4 as well. An ext4 file
system in a UBI volume can only be used read-only through ubiblock, so
these images are of no use.
They are broken anyway: the ext4 images are gzipped as a whole, which
moves the metadata of the sysupgrade image into the gzip stream. fwtool
reads the metadata from the end of the file, so sysupgrade rejects the
image with "Image metadata not present".
Build the UBI images for squashfs only.
Link: https://github.com/openwrt/openwrt/pull/25658
Signed-off-by: Paul Spooren <mail@aparcar.org>
Four places wrote a route's entry the same way: skip a host route that
a local route shadows, take the host slot it holds or a free one, or
place a prefix row when it has none, then write it. Fold that into
otto_l3_route_install(), which returns 0, or -ENOSPC with the errors
they logged, and let each caller keep its own reaction: with no slot,
otto_l3_host_route_trap() and otto_l3_fib_add_v4() free the route,
otto_l3_route_update_hw() returns before the next hop, and
otto_l3_route_trap_new() leaves it. otto_l3_route_trap_hw() now ends in
otto_l3_route_rewrite(), which writes a route where it already is.
The handling stays the same. The one visible difference is that
otto_l3_route_update_hw() logs "Got slot for route" at debug level, as
the other paths did.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303), main against this change,
in the bench rounds on switch addresses that shadow main routes, on IPv4
multipath with a neighbour going away and coming back, on trap rows and
on source-specific IPv6 routes: 17 of 17, 15 of 15, 46 of 46 and 20 of
20 on both.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25651
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The next change calls it from otto_l3_route_trap_hw(), which comes
earlier in the file. Move it, unchanged, to just before that function.
No functional change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25651
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The Build/haier-sim_wr1800k-factory recipe produced non-reproducible images for two reasons:
* openssl aes-256-cbc -salt generates a random salt on every run, which is embedded in the Salted__
header and feeds key derivation, so identical input yields different ciphertext each build.
* tar -czf embeds the current time in both the gzip header and records member mtimes, uid/gid and
permission bits taken from the build environment (umask-dependent).
Fix by encrypting with a fixed salt instead of a random one, and by creating the archive with
deterministic tar options (sorted member order, zeroed uid/gid, normalized permissions via
--mode=go-w and mtime pinned to SOURCE_DATE_EPOCH when set (guarded by $(if ...)), piped through
`gzip -n`. The salt "4f70656e57727421" was obtained from `echo -n 'OpenWrt!' | xxd -p`.
Signed-off-by: Ryan Leung <untilscour@protonmail.com>
Link: https://github.com/openwrt/openwrt/pull/25605
Signed-off-by: Paul Spooren <mail@aparcar.org>
The GitHub CI spends 10 to 18 minutes rebuilding all host tools in most
"Check Kernel patches" jobs, although the tools container ships them
prebuilt. Before, the "Build tools" step took about 10 seconds.
The refresh sets all stamps to one time given to touch -t, which has a
resolution of a full second, so the fraction is zero. The CI job runs the
refresh about 0.2 seconds after actions/checkout finished, and git writes
the tools directory last. Its files therefore often get a timestamp in
the same second as the stamps, but after the full second. Since
timestamp.pl compares the fraction of a second, these source files are
newer than the stamps and every tool gets cleaned and built again.
Take the time from a freshly created temporary file and set all stamps
to it with touch -r. They still share one timestamp, but it now includes
the fraction and is always later than the checkout.
Fixes: 3cf47c5c17 ("build: compare timestamps with a fraction of a second")
Assisted-by: Claude:claude-opus-5-5
Link: https://github.com/openwrt/openwrt/pull/25626
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
33a031c818ad dns: bound dns_query() AVL walk with avl_is_last()
15a507e099ff cache: terminate cached TXT record inside its allocation
7ff4347014bd dns: check record allocation in dns_packet_answer()
7aa74cc1239f dns,interface: guard against NULL ifa_addr and getifaddrs() failure
4d3628f8634e ubus: bound TXT copy in umdns_announcements()
93b2903c92f8 service: initialise SRV priority and weight
5dc24e8c80d9 dns: handle missing unicast interface in parse_question()
ba53b7c932e8 service: validate txt entries and stop leaking on empty ones
e115784cb334 dns: reset packet after each batch in dns_query_pending()
126426e66e19 interface: compare full IPv6 address in source check
e035293d1d2b dns: include stdbool.h in dns.h
5b9638a13631 tests: stub the udebug helpers
defe7ccfd202 tests: add fuzz corpus entry for the dns_query() AVL walk
Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-j2f2-273j-r86h
Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-fc92-h6gc-rjjx
Link: https://github.com/openwrt/openwrt/pull/25620
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Add support for getting the caldata via NVMEM cells.
It will first try to use the ath10k style calibration NVMEM cells, and then
failover to the existing file based loading.
It should allow dropping most of the userspace caldata loading.
Link: https://github.com/openwrt/openwrt/pull/25566
Signed-off-by: Robert Marko <robimarko@gmail.com>
The aarch64 toolchain is built without --with-cpu, so the
CPU_CFLAGS_<type> entry in target.mk is the only place a -mcpu option
comes from. The cortex-a72 (bcm27xx/bcm2711, mvebu/cortexa72) and
cortex-a76 (bcm27xx/bcm2712) CPU types have no entry, so userspace for
these subtargets is built with plain "-Os -pipe", which produces
generic armv8-a code. The "doesn't correspond to a known type" warning
is not visible because the target scan discards stderr.
Add the missing entries. For cortex-a76 this also enables the ARMv8.2
features such as LSE atomics, which replace the out of line atomic
helper calls.
Fixes: 2534141322 ("mvebu: add support for MACCHIATObin (cortex-a72)")
Fixes: 5e928acf22 ("brcm2708: add bcm2711 subtarget (RPi 4B aarch64)")
Fixes: 8b63d9ac4a ("bcm27xx: add new bcm2712 subtarget")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Link: https://github.com/openwrt/openwrt/pull/25627
Signed-off-by: Robert Marko <robimarko@gmail.com>
The rhltable keyed on the gateway had two lookups. In
otto_l3_nexthop_update() it only let a gateway that no route has leave
early; for one that some route has, the function walked routes_list
right after. otto_l3_fib_del_v4() looked the route up by gateway,
though otto_l3_route_find() had already found it by table and
destination a few lines earlier. Both run on the single-threaded queue
that already walks the list without a lock, and the tables are small,
so the list serves both. The table goes, with its init, destroy, insert
and remove, and the insert failure path; the comments and log lines
that spoke of it are reworded.
The handling stays the same: a neighbour update still returns -ENOENT
for a gateway that no route has, and a delete still tears the route of
that destination down only if it is via that gateway. Of the two errors
for a route not found on delete, by gateway and by destination, the
second one remains.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303), before and after: a route
via a host forwards, traps once the host's neighbour entry is deleted
and forwards again once it is resolved, and its delete leaves no row.
The bench rounds on trap rows and on source-specific IPv6 routes pass
46 of 46 and 20 of 20, as before.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25643
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The rule placed every video4linux and media node in video-capture, but
most are not capture devices: on an rk3588 board five of the six V4L2
nodes are the RGA blitter and the Hantro and rkvdec stateless codecs,
and only the HDMI receiver captures anything. A media player then had to
join video-capture to reach a decoder, which also granted it every
camera on the box.
Put the DRM and media nodes in video, and add v4l-id, which runs
VIDIOC_QUERYCAP and prefers device_caps over capabilities so that what
it describes is the node. Given a device alone it prints one boolean per
V4L2_CAP_ flag as JSON. Given a rule string as well, a list of
CAP[,CAP...]:GROUP separated by semicolons in which * matches any node,
it puts the node into the group of the first rule which matches it.
The rule string is parsed in full before the device is opened, so a
capability name the kernel does not define is reported whichever rule it
appears in, and no node is touched. A V4L2 node is created with no group
and v4l-id assigns one, since exec is queued by procd and may not run at
all; holding the node at root until the driver answers keeps a camera
out of video.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
L3_FORWARD had one user, the action of a router MAC entry, and the
same value as ROUTE_ACT_FORWARD. Use that one and drop the duplicate.
No functional change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25641
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
uhttpd.init appends four random bytes as hex digits to the default
organization of its self-signed certificate. Without -v, hexdump prints
"*" instead of repeated lines, and with the format used here each byte
is a line of its own. When adjacent bytes are equal, the organization
gets a "*" instead of the repeated bytes, followed by a newline if more
bytes follow. For example 8b 35 35 ba gives "OpenWrt8b35*", a newline
and "ba". This happens for about 1 in 86 generated certificates.
Pass -v to hexdump, so all four bytes are printed.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25628
Signed-off-by: Robert Marko <robimarko@gmail.com>
otto_l3_fib_add_v4() programmed a multipath route through its first
next hop, fib_info_nh(fi, 0), so the switch sent all of its traffic to
that gateway while the kernel spreads it over all of them. Treat a
route with more than one path like the other routes the hardware cannot
carry: it gets a trapping entry, and the CPU routes its traffic. The
overview at the top of l3.c is updated to match.
A route that goes from one path to several, or back, arrives as a
replace and moves between the two kinds of entry. otto_l3_fib_del_v4()
takes a multipath route through the same branch, which finds its trap,
or nothing where none was written. RTL839x, which routes through PIE
rules and has no trapping entries, now leaves a multipath route to the
CPU instead of forwarding it through its first next hop; not tested
there.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with 10.99.90.0/24 through
two hosts and one echo sent to each of 16 destinations in it. On main
the row forwards and all 16 reach the first gateway; with this change
the row traps and the CPU spreads them, 6 and 10. On both, a single-path
replacement forwards all 16 to its gateway, going back to multipath
returns to the behaviour above, and the delete leaves no row.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25640
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
otto_l3_930x_route_lookup_hw() polled the execute bit of the CAM lookup
until it cleared, with no limit, so an engine that never answered would
hold the FIB work, and rtnl with it, for good. Poll it with
readx_poll_timeout(), with the 20 us step and 10 ms limit the table
accessors use, and return -ETIMEDOUT when the limit runs out.
The only caller, otto_l3_route_remove(), asks for the lookup when a
prefix route is not at the row it was written to. After a timeout the
route may still hold a row that the block, counted from the routes
left, no longer includes, so the next placement would shift rows over a
live route. Report the timeout and declare the prefix rows stale, as a
failed row move does: what is in the table keeps working and can still
be removed, and no route is placed again until the driver is reloaded.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with a bench-only debugfs
switch. Sending every prefix route removal through the lookup, three
routes went, each found by it, with no row left. Making the poll wait
for a condition that never comes, the removal logged the timeout and
left the row, and a prefix route added next got no row; no splat. The
bench rounds on trap rows and on source-specific IPv6 routes pass 46 of
46 and 20 of 20.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25639
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
otto_l3_probe() ignored what rhltable_init() returned and went on to
insert the catch-all rows into the table, and a later failure in probe
would have otto_l3_remove() destroy it, set up or not. Fail the probe
before anything uses the table.
With the constant parameters the driver passes, rhltable_init() cannot
fail on 6.18: it only rejects invalid parameters, and its bucket
allocation falls back to __GFP_NOFAIL. This changes no behaviour today;
it keeps a future failure from reaching a table that was never set up.
Boot-tested on a Hasivo S1100W-8XGT-SE (RTL9303); the failure path
cannot be reached there.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25638
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Currently, AX89X MAC is read for the ethaddr U-Boot env variable, but this
variable is only set if user interrupted boot and ran saveenv before.
So, instead of relying on U-Boot, lets read the MAC from the same place as
U-Boot, from the Factory UBI volume.
There is also a Factory2 UBI volume, but MAC-s in both must be indentical
as Factory2 is only used during upgrade to store the new versions.
Factory UBI volume has 2 MAC-s, one at 0x100e and one at 0x1014.
U-Boot uses the one at 0x100e and increments it by one, so we do the same.
Fixes: f50435627d ("qualcommax: ipq60xx/ipq807x: convert to PPE networking stack")
Link: #24604
Signed-off-by: Robert Marko <robimarko@gmail.com>
The RTL930x L3 offload was behind NET_DSA_RTL83XX_RTL930X_L3_OFFLOAD,
marked experimental and not set in any subtarget config, so a kernel
built from those configs had an empty RTL930x L3 configuration and no
offload. Remove the symbol and what came with it: the __maybe_unused
markers on the RTL930x helpers, and the #ifdef around the commented-out
IPv6 hash and MTU helpers in rtl930x.c, which stay as they are.
On RTL930x the offload now starts at probe: the L3 controls are
programmed, the two catch-all rows are written, the FIB is replayed
into the tables and debugfs gets realtek_otto_l3. RTL838x, RTL839x and
RTL931x take their configuration by compatible and never depended on
the symbol, so nothing changes there at run time. Their kernels now
carry the RTL930x code as well: l3.o grows from 26472 to 36748 bytes of
text and data on rtl838x, and from 26664 to 36940 on rtl839x.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with an image built from
the rtl930x config as it is, which no longer has any offload symbol:
the offload starts on its own, and the bench rounds on trap rows,
source-specific IPv6 routes and policy rules pass 46 of 46, 20 of 20
and 47 of 48, the results of images built with the symbol set. The one
miss is the test's own: it expects no packet at the gateway, but the
trapped packets reach it through the kernel, which routes them by main.
Compile-tested for rtl930x, rtl838x and rtl839x.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25636
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Much of the L3 offload in these two files was written with AI
assistance, in the fixes and the IPv6 offload merged since September
2026. Add a copyright line for that work, naming the models that
assisted it, as the Assisted-by trailers of those commits do.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25636
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The L3 offload grew over many changes and only its pieces were
commented. Add an overview at the top of l3.c: how the families route
(the RTL930x L3 tables against the PIE rules of RTL838x and RTL839x),
how the driver keeps the RTL930x tables in step with the kernel, and
what each family offloads, traps or leaves out. No code change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25636
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Enable the Bluetooth UART and pin configuration for Linksys Velop WRT
Pro 7 (LN6001/MBE70). Describe the ISP and reset outputs through the
existing named GPIO export mechanism, holding both high at boot.
Select the generic bluetooth-uart package in DEVICE_PACKAGES so images
include kmod-hci-uart and BlueZ btattach through its dependencies.
Initialize the LN6001 UCI defaults to attach /dev/ttyMSM1 using H4 at
115200 baud. Preserve already configured UARTs, including disabled ones.
The generic package remains disabled until a board or user configures it.
The combined series passed cold-start controller initialization, LE
discovery, connection and service discovery without a userspace reset
pulse. Keep Bluetooth support separate from Wi-Fi enablement.
Signed-off-by: Satoshi Ikeuchi <satosan.ikm@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25594
Signed-off-by: Robert Marko <robimarko@gmail.com>
Use a generic procd service around the foreground BlueZ btattach utility.
Configure the UART, protocol and speed through UCI, without router
identity checks or GPIO operations in the attachment service.
Leave attachment disabled and the device unset by default. Keep board
wiring in the device tree and use the existing HCI UART and BlueZ packages.
Tested controller startup after cold power-on, LE discovery, connection
and service discovery on LN6001.
Signed-off-by: Satoshi Ikeuchi <satosan.ikm@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25594
Signed-off-by: Robert Marko <robimarko@gmail.com>
An -addext value is only consumed if it starts with "extendedKeyUsage="
or with "subjectAltName=" and contains a colon. Any other value, for
example "subjectAltName=localhost" or the OpenSSL spelling
"subjectAltName = DNS:x", stops the option parser, so px5g ignores all
options after it, for example -keyout and -out. A comma separated list
like "DNS:a,DNS:b", as OpenSSL takes it, ends up as a single bogus
name. An empty name like "subjectAltName=DNS:" is written into the
certificate, although OpenSSL refuses it. Email addresses are only
accepted with the type EMAIL, while OpenSSL calls it email.
extendedKeyUsage has similar problems. A value other than serverAuth or
any leaves an empty OID in the extension, values are matched by prefix,
and only the last of several extendedKeyUsage options is used.
Fail with an error on unsupported values, on empty names and on any
comma in a subjectAltName, which OpenSSL takes as a separator even in a
URI. Accept the type email as well. Compare the usage exactly, also
accepting the OpenSSL name anyExtendedKeyUsage, and keep all given
usages. Check the result of adding them and fail if mbedtls refuses
them, for example 26 serverAuth values, which do not fit its buffer.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25604
Signed-off-by: Robert Marko <robimarko@gmail.com>
The subjectAltName support added in commit efca89daef ("px5g-mbedtls:
add subjectAltName and extendedKeyUsage to SSL certs") has these bugs:
- Every IP entry is written with a length of 16 bytes. An IPv4 address
ends up as a zero padded IPv6 address, so 192.168.1.1 becomes
C0A8:101:: and clients reject the certificate for that address.
- All IP entries share one buffer, so each of them carries the address
given last.
- An invalid IP address is not rejected but written as :: or as the
address of an earlier IP entry.
- The list is linked after every option instead of only after a new
entry. If any other option follows the last subjectAltName, that
entry points to itself. Adding the extension then loops until the
size counter overflows, which never ends on 64-bit targets and drops
the whole extension on 32-bit targets.
- An unknown entry type only prints a warning. It stays in the list
with type 0, which mbedtls cannot write, so the whole extension is
dropped while px5g still exits with 0.
- Without any subjectAltName, the extension is written with an empty
list, which RFC 5280 does not allow. Chrome rejects such a
certificate with ERR_CERT_INVALID and, unlike for other self-signed
certificates, does not offer to proceed.
Use the length returned by mbedtls_x509_crt_parse_cn_inet_pton(),
allocate a buffer for each IP entry and link only new entries. Reject
invalid IP addresses and unknown entry types with an error. Add the
extension only if there are entries and fail with an error if mbedtls
refuses it.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25604
Signed-off-by: Robert Marko <robimarko@gmail.com>
The four SoC-specific net_device_ops tables differ only in their RX mode
and feature callbacks.
Move the RX mode callback and RX checksum mask into rteth_cfg and use
shared wrappers with a single net_device_ops table. Preserve the existing
RX mode handlers and checksum control bits for each SoC.
This removes duplicated callback tables without changing driver behavior.
Assisted-by: ChatGPT (OpenAI GPT-6.1 Sol)
Link: https://github.com/openwrt/openwrt/pull/25574
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Add kmod-usb-storage-uas to the default package set for the Turris
Omnia and Turris MOX.
Both devices provide USB host ports that can be used with fast USB
storage devices such as SSDs. UAS provides a more efficient transport
than the legacy USB Mass Storage Bulk-Only Transport and allows such
devices to better utilize the available USB bandwidth.
Without the UAS driver installed, compatible devices silently fall
back to the legacy transport, which can limit storage performance.
Users may not realize that kmod-usb-storage-uas needs to be installed
separately.
The package is only about 10 KiB and remains a loadable kernel module,
so users can remove it independently if a particular USB storage
device has compatibility issues.
Signed-off-by: Josef Schlehofer <pepe.schlehofer@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24742
Signed-off-by: Robert Marko <robimarko@gmail.com>
zlib-ng built with ZLIB_COMPAT provides libz.so.1 with the zlib API and
ABI, and carries maintained SIMD code with runtime CPU detection: NEON
on ARM, the ARMv8 CRC32 instructions, and SSE/AVX on x86.
zlib-ng 2.3.3 lacks the functions zlib 1.3.1.2 and 1.3.2 added:
deflateUsed() and the size_t variants compress_z(), compress2_z(),
compressBound_z(), deflateBound_z(), uncompress_z() and uncompress2_z().
Backport both from zlib-ng develop, and the zlib.map.in change of
zlib-ng PR 2403 that exports deflateUsed under ZLIB_1.3.1.2, so libz.so.1
exports every symbol and version node of zlib 1.3.2.
Build with -DNO_QUICK_STRATEGY. deflate_quick makes level 1 output of a
4 MiB text file 20% larger than zlib's; levels 3 to 6 keep
deflate_medium.
Install zlib_name_mangling.h, which the compat zconf.h includes. The
host build in tools/zlib stays on zlib.
On IPQ8074 (Cortex-A53), 4 MiB of text, median of 3 interleaved runs:
inflate 34.0 -> 22.7 ms, deflate level 6 460 -> 270 ms. libz.so.1 grows
by 18.9 KiB on aarch64, 9.8 KiB on arm_cortex-a7 and 9.1 KiB on
mips_24kc, 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/25570
Signed-off-by: Robert Marko <robimarko@gmail.com>
Patch 004 builds vendored copies of inflate.c and inffast.c from 2017
(madler/zlib#256, never merged) instead of the stock files on 32-bit
ARM targets with NEON. The vendored inflate.c lacks the CVE-2022-37434
fix that zlib 1.2.13 and later carry.
Drop the patches and the NEON probe, so every target builds stock
zlib. aarch64 is unaffected: gcc does not define __ARM_NEON__ there,
so the probe never enabled the vendored files.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25570
Signed-off-by: Robert Marko <robimarko@gmail.com>
A prefix with source-specific IPv6 routes gets one trap row, which
keeps a list of their sources and goes once the list is empty and no
route without a source is left. When the allocation for a source
failed, that source was left out: once the list was empty the row
went, or a route without a source took it over, though the kernel
still had the source-specific route the row was trapping for.
Mark the row when a source could not be tracked, count it as still
standing for sources, and ask for a FIB replay, which builds the list
again from scratch.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
through a bench-only debugfs counter that fails the next source
allocation: under an IPv6 /32 forwarding in hardware, a /48 with a
source-specific route via another host and a source-specific blackhole
for the sender, whose tracking fails. Once the first is deleted, the
kernel drops the sender's echoes: without this change the trap row
goes and the /32 forwards all 5 to the host, with it the row stays, the
FIB is replayed and none arrive.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25623
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
otto_l3_host_route_alloc() and otto_l3_route_alloc() differ only in the
table the id comes from (its bitmap, size and name in the table-full
error), the offset a host route's id gets, and is_host_route. Fold them
into one routine that takes the kind of route, ROUTE_HOST or
ROUTE_PREFIX. No functional change.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled:
the bench round on host and prefix route placement, 46 checks on host
routes, prefix trap rows and replacements, passes 46 of 46, as it does
on main.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25621
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Remove stopped the notifiers and drained the driver's queue, but only
released the IPv6 FIB entries the routes held: the route objects, their
source lists and the hash table stayed allocated. The table's resize
work is not on the driver's queue either, so one still pending could
run after unbind had freed the controller.
Free every route with the helper a delete ends with, under rtnl as its
other callers hold it, and destroy the hash table, which also cancels
or waits for its resize work. The hardware rows stay as they were, as
before; the kernel's IPv6 routes lose their offload mark. Probe now
cleans up the same way when the netevent notifier cannot be registered,
after the catch-all rows are already in.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
unbinding the switch driver with 300 routes programmed (200 IPv4
prefixes, 50 IPv4 host routes, 50 IPv6 prefixes; 321 driver rows with
the catch-all ones). Unreclaimable slab memory went down by 100 kB
across the unbind without this change and by 224 kB with it; the 50
IPv6 routes kept their offload mark without it and lost it with it. No
warning or oops either way.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25622
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
When a gateway's neighbour goes away, the routes through it are turned
into traps. A route whose address had no entry in the host table
returned before recording that, so it still said forward, and a main
/32 that later got the entry back when a local address went was
programmed to forward through the neighbour that had gone.
Record the trap before looking for the entry. Only RTL930x has a host
table.
Not reproduced on hardware: it needs a host route that found no free
entry in the host table.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25619
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
While an address is the switch's, its host entry is the local route's
and a main /32 for the address keeps out of it. When the kernel
replaces the local route by another for the same address, as when an
address held on two devices is removed from the first, the driver tears
the old route down, which hands the entry back to the main /32, and
then writes the new local trap over it. In between, the hardware can
forward packets for the switch's own address through the main /32's
gateway.
A route torn down to be replaced no longer hands the entry back; the
route replacing it takes it over. The entry is still invalidated in
between, so for that moment a covering prefix answers. Only RTL930x has
a host table.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
through a bench-only line logged whenever a main /32 gets its entry
back: with an address on two switch interfaces and a main /32 for it
via another host, removing the address from the first interface logs
that write without this change and none with it. Removing it from the
second logs it on both, and the main /32 forwards 5 of 5 echoes again.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25619
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Use the new ucidef_set_led_brightness function for the ST LED1202 status
LEDs now that it supports configurable brightness. Blue is enabled at
brightness 51 with red and green off, matching the OEM default colour
scheme and intensity.
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23457
Signed-off-by: Robert Marko <robimarko@gmail.com>
Add ucidef_set_led_brightness() to set up a static LED with an optional
brightness level, complementing ucidef_set_led_default() for hardware
that supports per-channel current or PWM control.
The function writes a "brightness" type to board.json alongside the
default on/off state. config_generate picks this up and writes the
brightness option to the UCI LED config, where the led init script
already knows to apply it.
Signed-off-by: Manuel Fombuena <fombuena@outlook.com>
Link: https://github.com/openwrt/openwrt/pull/23457
Signed-off-by: Robert Marko <robimarko@gmail.com>
The Allwinner H5 uses the H3 R-PIO controller in addition to its
H5-specific main PIO controller. Moving the pinctrl configuration to
the subtargets left PINCTRL_SUN8I_H3_R disabled for cortexa53.
On the NanoPi NEO 2, usb0-vbus depends on the R-PIO PL2 GPIO. Without
the driver, the regulator and USB PHY remain deferred, preventing the
USB host controllers from probing. No USB device nodes are created
and lsusb reports "unable to initialize libusb: -99".
Enable PINCTRL_SUN8I_H3_R in the cortexa53 configuration to restore
the R-PIO driver required by H5 boards.
Fixes: 920fa6f061 ("sunxi: enable pinctrl driver in subtarget")
Signed-off-by: Joseph Chen <phenomenon0102@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25588
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Since the MAC lookup started returning -EPROBE_DEFER, a probe that
defers while its nvmem provider (e.g. a mac-base cell in the CFE
partition) isn't ready yet leaves the power domain devices attached
by genpd_dev_pm_attach_by_id() behind. The next probe then fails to
re-create them:
sysfs: cannot create duplicate filename '/devices/genpd:0:1000d800.ethernet'
bcm6368-enetsw 1000d800.ethernet: error getting pm 0
bcm6368-enetsw 1000d800.ethernet: probe with driver bcm6368-enetsw failed with error -22
leaving the board without ethernet and the DSA switch deferred forever.
Look up the MAC first, before anything that isn't device-managed has
been set up, so a deferred probe can simply be retried.
Seen on a BCM6328 (BeWAN A2100N) with kernel 6.18.
Fixes: ed545519ee ("bmips: enet: handle EPROBE_DEFER for the MAC address")
Signed-off-by: Max Plekh <mplekh@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25454
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
A rule given an explicit dscp selector keeps it in the family's own
part of the rule, with a flag that tells dscp 0 from no selector at
all. fib4_rule_default() and fib6_rule_default() only test the dscp
value, so "dscp 0 lookup main" passed for an unrestricted main rule:
packets with any other dscp go on to the next rules in the kernel, and
the hardware forwarded them by main all the same.
Only the family's own callbacks see that part of the rule, and its fill
callback reports an explicit selector as FRA_DSCP. Run it into a
scratch buffer and count a local or main rule with FRA_DSCP, or one
that cannot be read out, as restricted.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled:
a prefix routed in main via a host on another VLAN, blackholed in
table 100, with "dscp 0 lookup main" ahead of a rule sending the
sender's subnet to table 100. Echoes with dscp 8: without this change
the row keeps forwarding and all 5 reach the host, with it the row
traps and none do, for IPv4 and IPv6. With it, echoes with dscp 0 still
reach the host, routed by the kernel through main.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25618
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Probe holds the FIB replay work disabled until the FIB notifier is in
place, and queueing a disabled work does nothing. The notifiers are
live before that, so one that could not allocate in the window asked
for a replay that never came, and what its lost event would have
changed could stay wrong in hardware.
Note the request in the control structure before queueing the work,
and have probe queue the work once it has enabled it if a request was
noted. The two barriers pair, so at least one side sees the other: the
notifier finds the work enabled, or probe finds the request. The work
clears the note when it starts. Where the work is never enabled, a
family that routes through PIE rules, the note is set and never read,
as the queueing does nothing there today.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
through a bench-only commit that asks for a replay right after the
netevent notifier is registered, as a notifier does when its allocation
fails: without this change no replay follows, with it the FIB is
replayed once probe has enabled the work, and a route added afterwards
is offloaded and forwards 5 of 5 echoes as before.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25617
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
The switch looks a destination up in rows built from the local and main
tables, while the kernel consults the policy rules first. A rule ahead
of main can send a packet to another table, and a main rule restricted
to some packets, or no main rule at all, sends the others elsewhere;
the hardware forwarded them by main all the same. Rule events of both
families went to fib4_rule_default(), which only logged "FIB4 default
rule failed".
On every rule event, look at that family's rules. The local rule, an
unrestricted main rule and rules at a later priority leave the offload
as it is: such a rule only sees what main has no route for, and no row
forwards that either. Any other rule before main or at main's
priority, or a missing or restricted main rule, turns the family's
forwarding rows into traps, and they go back to forwarding through
their gateways once the rules allow it again. A rule that only matches
iif lo never sees a forwarded packet and does not count.
fib4_rule_default() and fib6_rule_default() tell a default rule; they
leave ip_proto and the fwmark mask out, so a rule with either does not
pass for main here. A main rule restricted to dscp 0 still does: the
kernel keeps that in a structure the driver cannot see.
The rows are rewritten where they are; a main /32 kept out of a local
address's host entry stays out of it. This changes the L3 table path
only. A family that routes through PIE rules keeps its rules and the
error it logged, now for IPv4 rules only.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled:
a prefix routed in main via a host behind another port, blackholed in
table 100, pinged from a third subnet. With a rule sending that subnet
to table 100 ahead of main, the hardware without this change still
forwards all 5 echoes to the host; with it the rows trap and none
arrive, for IPv4 and IPv6 independently. A main rule restricted to
another source subnet gives the same 5 against 0. Rules at a later
priority than main, iif lo rules and the default rules keep the rows
forwarding, and rows that trapped come back once the rules do.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25612
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Both notifiers allocate their work with GFP_ATOMIC and return
NOTIFY_BAD when that fails. The kernel takes that as a veto only for a
route or a rule being added; a route delete or a neighbour update goes
ahead regardless, and the hardware keeps forwarding by what the lost
event would have changed.
On such a failure, queue a work item kept in the driver's control
structure, which needs no allocation. It unregisters the FIB notifier,
takes out every route the driver programmed and registers it again, so
the kernel replays the FIB as it does at probe. The stale entry still
forwards until that flush, which waits for the work already queued;
from there until the replay is done, the catch-all rows trap what the
routes no longer cover. A replay can fail too, short of memory the
same way or on a route the notifier refuses that came in while it was
away: it is flushed and tried again after a delay that doubles up to
64 seconds. An add the kernel refused schedules a replay as well, which
finds nothing to correct.
The work is enabled once probe has registered the notifier, and only
where the L3 tables provide the catch-all rows; a family that routes
through PIE rules keeps the old behaviour. Remove disables it before
unregistering the notifiers.
Tested on a Hasivo S1100W-8XGT-SE (RTL9303) with L3 offload enabled,
through bench-only debugfs counters that make the next allocations of
either notifier fail. A route deleted while its event is lost: without
this change its row keeps forwarding and 5 of 5 echoes still reach the
old gateway; with it the replay takes the row out and none do. A
permanent neighbour moved to another host while its event is lost:
without this change all 5 echoes still go to the old host, with it to
the new one. With the replay's first allocation failing as well, the
replay fails once and the retry converges the same way. An add whose
event is lost is refused either way. The untouched IPv4 and IPv6 routes
forward in hardware after every replay.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net>
Link: https://github.com/openwrt/openwrt/pull/25603
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
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>
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>
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>