bolvan wrote:odhcp6c only receives and interprets RAs. It does not make any changes to system, ips, routes,... For this it calls /lib/netifd/dhcpv6.script. Debug this script to understand what it does. Modern openwrt versions push ips/routes to netifd using shell helper functions. They construct json query and send it to netifd thru ubus.
Netifd is responsible to making actual changes.
ifstatus <ifname> shows internal netifd state of a given logical interface
I added some logging to the /lib/netifd/dhcpv6.script.
When the RA message is received, the $RA_ROUTES variable seems to have the correct info:
::/0,fe80::Y:Y:Y:Y,1800,512
2001:470:6db5::/64,,2592000,256
But the default route (::/0) never makes it into the routing table:
(I'm redacting the host IDs)
# route -A inet6
Kernel IPv6 routing table
Destination Next Hop Flags Metric Ref Use Iface
2001:470:6db5::/64 :: U 256 0 0 eth1
fe80::/64 :: U 256 0 0 eth0
fe80::/64 :: U 256 0 0 eth1
::1/128 :: U 0 0 1 lo
2001:470:6db5::/128 :: U 0 0 1 lo
2001:470:6db5:0:X:X:X:X/128 :: U 0 0 1 lo
fe80::/128 :: U 0 0 1 lo
fe80::/128 :: U 0 0 1 lo
fe80::X:X:X:X/128 :: U 0 0 1 lo
fe80::X:X:X:X/128 :: U 0 5 1 lo
ff02::1/128 :: UC 0 75 0 eth1
ff02::2/128 :: UC 0 3 0 eth1
ff02::1:2/128 :: UC 0 2 0 eth1
ff00::/8 :: U 256 0 0 eth0
ff00::/8 :: U 256 0 3 eth1
The problem seems to be in the following code in the "for entry in $RA_ROUTES" part of dhcpv6.script:
if [ -z "$SOURCE_ROUTING" -o -z "$gw" ]; then
logger -p user.info -t "my_dhcpv6[$$]" "if.. $addr $mask $gw $metric $valid"
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid"
else
logger -p user.info -t "my_dhcpv6[$$]" "else.. $addr $mask $gw $metric $valid"
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" "::/128"
for prefix in $PREFIXES $ADDRESSES; do
local paddr="${prefix%%,*}"
logger -p user.info -t "my_dhcpv6[$$]" "loop.. $addr $mask $gw $metric $valid $paddr"
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid" "$paddr"
done
fi
Of the 2 routes in the $RA_ROUTES variable, the 2001:470:6db5::/64 address gets handled by the 'if' and seems fine. The ::/0 address gets handles by the else, and again by the for loop within the else clause.
This leads to a duplicate entry in netifd:
# ifstatus wan0
{
"up": true,
"pending": false,
"available": true,
"autostart": true,
"uptime": 356,
"l3_device": "eth1",
"proto": "dhcpv6",
"device": "eth1",
"metric": 0,
"delegation": true,
"ipv4-address": [
],
"ipv6-address": [
{
"address": "2001:470:6db5:0:X:X:X:X",
"mask": 64,
"preferred": 604796,
"valid": 2591996
}
],
"ipv6-prefix": [
],
"ipv6-prefix-assignment": [
],
"route": [
{
"target": "2001:470:6db5::",
"mask": 64,
"nexthop": "::",
"metric": 256,
"valid": 2591996,
"source": "::\/0"
},
{
"target": "::",
"mask": 0,
"nexthop": "fe80::Y:Y:Y:Y",
"metric": 512,
"valid": 1796,
"source": "2001:470:6db5:0:X:X:X:X\/64"
},
{
"target": "::",
"mask": 0,
"nexthop": "fe80::Y:Y:Y:Y",
"metric": 512,
"valid": 1796,
"source": "::\/128"
}
],
"dns-server": [
],
"dns-search": [
],
"inactive": {
"ipv4-address": [
],
"ipv6-address": [
],
"route": [
],
"dns-server": [
],
"dns-search": [
]
},
"data": {
}
}
If I remove the whole if-else block, and replace it with a single line
proto_add_ipv6_route "$addr" "$mask" "$gw" "$metric" "$valid"
then everything works:
# route -A inet6
Kernel IPv6 routing table
Destination Next Hop Flags Metric Ref Use Iface
2001:470:6db5::/64 :: U 256 0 0 eth1
fe80::/64 :: U 256 0 0 eth0
fe80::/64 :: U 256 0 0 eth1
::/0 fe80::Y:Y:Y:Y UG 512 0 0 eth1
::1/128 :: U 0 0 1 lo
2001:470:6db5::/128 :: U 0 0 1 lo
2001:470:6db5:0:X:X:X:X/128 :: U 0 0 1 lo
fe80::/128 :: U 0 0 1 lo
fe80::/128 :: U 0 0 1 lo
fe80::X:X:X:X/128 :: U 0 0 1 lo
fe80::X:X:X:X/128 :: U 0 8 1 lo
ff02::1/128 :: UC 0 4 0 eth1
ff00::/8 :: U 256 0 0 eth0
ff00::/8 :: U 256 0 1 eth1
# ifstatus wan0
{
"up": true,
"pending": false,
"available": true,
"autostart": true,
"uptime": 91,
"l3_device": "eth1",
"proto": "dhcpv6",
"device": "eth1",
"updated": [
"addresses",
"routes"
],
"metric": 0,
"delegation": true,
"ipv4-address": [
],
"ipv6-address": [
{
"address": "2001:470:6db5:0:X:X:X:X",
"mask": 64,
"preferred": 604699,
"valid": 2591899
}
],
"ipv6-prefix": [
],
"ipv6-prefix-assignment": [
],
"route": [
{
"target": "2001:470:6db5::",
"mask": 64,
"nexthop": "::",
"metric": 256,
"valid": 2591899,
"source": "::\/0"
},
{
"target": "::",
"mask": 0,
"nexthop": "fe80::Y:Y:Y:Y",
"metric": 512,
"valid": 1699,
"source": "::\/0"
}
],
"dns-server": [
],
"dns-search": [
],
"inactive": {
"ipv4-address": [
],
"ipv6-address": [
],
"route": [
],
"dns-server": [
],
"dns-search": [
]
},
"data": {
}
}
Can anyone explain what's going on?
I don't understand the significance of the 'source' option in IPv6 routes.
There is a one-line description here: https://wiki.openwrt.org/doc/uci/network#ipv6_routes. This sounds like NAT to me; what has it got to do with a route?