mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-14 08:47:51 +04:00
realtek: l3: rtl930x: test the slot that was read
otto_l3_930x_find_slot() probed the host route table and then looked at the caller's route instead of the entry it had just read. The placement test asked rt->attr.valid, which both call sites set to true right before calling, so the first address probed was always returned: of the 6144 host route slots only the 512 bucket heads of the first table were reachable, and a second route in a bucket overwrote the first. The lookup test compared route_entry.dst_ip, which otto_l3_930x_host_route_read() does not touch when the entry is invalid or is not IPv4 unicast, so it could match an address the reader never wrote. Ask the entry that was read: an empty slot for placement, and for a lookup a valid entry of the same type whose destination matches. IPv6 unicast destinations are compared with ipv6_addr_equal() instead of through the IPv4 field. Measured on an RTL9303 (Hasivo S1100W-8XGT-SE): two /32 host routes hashing to bucket 281 both ended up at logical index 1686 before this patch. With it each route takes a slot of its own, which is also what exposed the duplicate writes the next patch removes. Assisted-by: Claude:claude-opus-5 Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net> Link: https://github.com/openwrt/openwrt/pull/25170 Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
This commit is contained in:
1 parent
522cb4b864
commit
4344b47ebc
1 file changed
+15
-3
@@ -297,10 +297,22 @@ static int otto_l3_930x_find_slot(struct otto_l3_ctrl *ctrl, struct otto_l3_rout
|
||||
otto_l3_930x_host_route_read(ctrl, idx, &route_entry);
|
||||
dev_dbg(ctrl->dev, "route valid %d, route dest: %pI4, hit %d\n",
|
||||
rt->attr.valid, &rt->dst_ip, rt->attr.hit);
|
||||
if (!must_exist && rt->attr.valid)
|
||||
return idx;
|
||||
if (must_exist && route_entry.dst_ip == rt->dst_ip)
|
||||
if (!must_exist && !route_entry.attr.valid)
|
||||
return idx;
|
||||
if (must_exist &&
|
||||
route_entry.attr.valid &&
|
||||
route_entry.attr.type == rt->attr.type) {
|
||||
switch (rt->attr.type) {
|
||||
case 0:
|
||||
if (route_entry.dst_ip == rt->dst_ip)
|
||||
return idx;
|
||||
break;
|
||||
case 2:
|
||||
if (ipv6_addr_equal(&route_entry.dst_ip6, &rt->dst_ip6))
|
||||
return idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user