IPv6: Ask for help: No re-connect to v6

Very good analysis and very quick. Thank you!
I’ll work on all points and will report.
Thanks for your attention and effort!

FRITZ.Box_7430-07.10.image

Cool - I was not able to find it. Thanks for the hint.
I’ll give it a try asap.
Thx!

UPDATE:
Today AVM provided the update via semi-automatic update from out of the GUI. 7.10 is applied now to 7430.

NO better in behaviour, problem still exists.
Rebooting FritzBox (current or GUI) leads to missing v6 connect by TO
:frowning:

Since Fritz 7.10 and a few system restarts I can not connect to IPv6 with any TO any more. Both devices do not connect to v6 any longer.

One more thing - if you follow OpenWRT upstream development or look at their bug tracker | filtered to ipv6 trunk and 18.06 you will see that there are plenty of issues with ipv6 and one or the other could pertain to this issue, that if TO is at fault and not the FB…

Also note that upstream trunk refers to their Master development, the future OpenWRT 19.x | TOS5.x branches, and patches are not always implemented/backported in current OpenWRT 18.x | TOS4.x branches

That is too bad…

If you want to get to the bottom of it and invest a bit time/effort you could run a tcpdump on the TO and analyse with a tool like wireshark the packet traffic between the FB (when rebooting/cold started) and the TO.
It should reveal whether the TO is requesting the ipv6 from upstream and also whether the FB is broadcasting it to the TO, respectively whether the packages are reaching the TO.
To my knowledge AVM does not provision tcpdump in their proprietary OS for the FB.

If I am not mistaken the tcpdump packet capture should cover traffic on UDP ports 546 and 547, e.g. on the TO via ssh cli

tcpdump -i [put the TO wan6 iface name here] udp portrange 546-547 -XXevvvw /tmp/[name your dump file here]

Once the capture is done download the dump file from /tmp via ssh to a client that runs wireshark and import the dump file for inspection

There is https://openwrt.org/packages/pkgdata/watchcat with corresponding https://openwrt.org/packages/pkgdata/luci-app-watchcat. It will not cure the issue (potential bug) but might better than cron, though I have not tried it.

Results:
Yes: All clients (hosts: Laptop and Desktop, Linux) directly connected to FritzBox do have full IPv6 access. No matter if Fritz rebooted hard or via GUI. Via Ethernet and WLAN. ipv6-test.com shows green :wink:

No connect any more if TO is in between (before FritzOS 7.10 it worked after TO reboot).

I exchanged the Fritz7430 against the provider box (o2 6441): IPv6 is operational for hosts (Ethernet)! Same host, same box, TO : no ipv6 connect for host.
TO (nr. 2) was resetted to factory settings: no different behaviour, no v6 traffic
No idea if this provider box o2 6441 can do PD properly.
Next I need to reset the Fritz7430 to factory (I can not go back to FritzOS 7.01, refuses). Will take some days.

Are you saying that none of your 2 TO has ipv6 upstream connectivity at all after update to F!OS 7.10, not even after rebooting the TO? And with the provider’s box it is the same?


Have tried also different ethernet cables between the TO and the upstream boxes?

Had a chance to almost replicate the setup, different FB model though and perhaps different upstream connectivity

  • upstream router F!box 7530 with ISP controlled F!OS 7.10
  • upstream ISP authentication PPPoE
  • upstream ISP connectivity DS-Lite, native IPv6 via DHCP and pre-fix (rotated every 12 hours) delegation in /56 range for the FB
  • TOS4.x beta 2

The result is rather curious

  • wan6 on the TO showing the delegated pre-fix from the FB with a /64 range
  • none of the other TO’s ifaces however getting an ipv6 with that delegated pre-fix and thus none of the TO’s clients

Reverting back to normal setup, removed FB and using a SFP DSL modem in the TO’s SFP port, the pre-fix from upstream gets propagated downstream all the way just just fine.

@Dietmar

If I use DHCPv6, interface name is wan_6 (not wan6)
It is not in the interface list.
Try it
ifstatus wan_6

Turris 1.x

Unfortunately I did not the time yet to do that traffic analysis. From what I learned here the FritzBox IPv6 may not be very well implemented.
However, there is a good tutorial to analyse the traffic here:

I follow up soon.

Turris Omnia is great. I love it.
Prefix delegation (PD) works successful and flawless in general. But …

issue:
Prefix delegation (PD RFC 3633 RFC 8415) does not always work as expected.
Client hosts do not get updated PD prefixed address in case of changes upstream.
Turris can not provide v6-Internet at all(!) if the upstream Internet-router was rebooted (or was completely down).

Environment:
Hosts: Average Linux x86 Desktop, Laptops running Ubuntu, IPv6, PD, EUI64, no issue here.
Router cascade: FritzBox7430 DSL + Turris Omnia
Turris OS Version 5.1.4, Turris OS branch hbs, Kernel-Version 4.14.206

Situation:
Regarding Turris as linchpin
Turris eth2 is upstream i.e. eth2 connects FritzBox to Turris
Turris br-lan is downstream i.e. downstream br-lan provides service to hosts via LAN1 and WLANs
Prefix delegation (PD) works successful and flawless in general! Good so far.
Setup in detail (German): https://www.schweinekraftland.de/Home_Network_access_IPv6/Home_Network_access_IPv6.htm

Analysis:
upstream:
If FritzBox experiences power failure or restart or reconnect (3 slightly different scenarios) we do have a change in the PD IP provided by the DSL provider.
The PD IP is actually acquired by FritzBox and successfully provided to Turris within short time (max. few minutes)

Turris upstream:
The upstream eth2 is retrieving and showing the new and valid PD IP (provided by FritzBox). Good.
Depending on the FritzBox szenario there will be an additional deprecated upstream PD IP: Not relevant.

Turris downstream:
Turris downstream br-lan does not show any new PD prefixed address.
It does not recognise the upstream change.
It remains as is: Showing the dysfunct, old PD prefixed address. Old global IPv6 address may change to deprecated state after some time (preferred_lft time =0).
If valid_lft and preferred_lft times both become zero (EOL) the assigned address disappears (OK) and is replaced by nothing (my observation).
Not OK IMHO.

Problem:
Then (almost?) indefinite this state remains constant:
Turris upstream has identified and uses the changed PD prefixed address successful,
Turris downstream is dysfunct: wrong IP or no valid PD prefixed address or no IP at all.
No single valid global IPv6 address means NO IPv6 for the client hosts possible!

Result:
No IPv6 service at all(!) for client hosts.

Workaround:
Script that (description abbreviated) detects if
upstream eth2 shows a deprecated global address (ip -6 -o address show scope global dynamic -deprecated eth2) *)
and
downstream br-lan actually has a deprecated address (a state that will exist for limited time; ip -6 -o address show scope global dynamic deprecated br-lan)
and then
restarts the network service on Turris Omnia.

Outcome workaround:
Restart of network service resolves the problem almost always. IPv6 service incl. PD prefixed addresses work fine then.
(simple script can be provided, no git yet)

Conclusion:
It would be helpful if Turris Omnia OpenWRT would forward the PD information from upstream eth(n) to downstream LAN/WLAN connected to br-lan bridge.

*) here the deprecated is negated using „-deprecated“ to exclude the state deprecated actively; specific documentation not yet found in http://linux-ip.net/gl/ip-cref/ or http://download.vikis.lt/doc/iproute-doc-2.6.32/ip-cref.ps

:wq

Hey,

mhmm, do I see correctly that Turris (and IMO oWRT) needs something what guys with Debian and isc-dhcp solve with dhcp-exit-hook ( https://wiki.debian.org/IPv6PrefixDelegation, chapter “Assigning the prefix to another interface”) ?

To be exact, to implement that logic into /lib/netifd/dhcpv6.script ?

The last time I checked my cable TV and Internet provider had no properly working PD at their boxes so I hard-wired everything manually :man_factory_worker:

EDIT:

In their script I see something like:

if [ -n "$old_ip6_prefix" ] || [ -n "$new_ip6_prefix" ]; then
    ( ... )
    ip -6 addr flush dev "$IA_PD_IFACE" scope global
    ( ... )
    ip -6 addr add "$new_ia_pd_addr" dev "$IA_PD_IFACE"
    ( ... )
    (restart needed services, like dnsmasq etc)   
1 Like

May I admit I like your reply very much, so?
quote: "Once a prefix has been obtained, it can be assigned to another interface. "
I did not check the details (my knowledge is limited).

However, it sounds very convincing :slight_smile: :slight_smile:

Reminds me of the simple script I wrote do do a similar thing (less elegant) cron based in Turris Omnia.

All providers I work with in Germany do provide native IPv6 meanwhile. All including PD. As there are DTAG, DtGlasfaser, DOCSIS-based TV stuff, Telefonica, direct and resale).
Based on this I connect to remote machines.

So yes, I’d like to encourage you to give it a try to implement the idea as a solution.
If I can help testing let me know.
I implemented more than one Turris Omnia and my personal one could be switched from HBS to Turtles or other animals…

Make little turtle happy, make the turtle http://[2001:200:dff:fff1:216:3eff:feb1:44d7]/ dancing!!

well, don’t put too much hope on me.Thanks to your detailed description we realized what’s wrong so far, that’s all. I must admit that because of corona and homeoffice, I’m supercareful when digging deeper in my Turris :slight_smile:

Inbetween I found, that in /lib/netifd/dhcpv6.script there is this section:

# user rules
[ -f /etc/odhcp6c.user ] && . /etc/odhcp6c.user "$@"

That means, we can inject our helpers without need of patching upstream. Good.
Create the /etc/odhcp6c.user file with this content:

#!/bin/bash
  
# dhcp6 "helper" to dump enviroment data when /lib/netifd/dhcpv6.script is called
date_string=$(date +"%Y_%m_%d_%H-%M-%S")
filename="/srv/temp/dh_debug__${date_string}" # replace with proper log path
echo "dump from ${date_string}" > ${filename}

echo "env:" >> ${filename}
env >> ${filename}

echo "--------------------------------------------" >> ${filename}
echo "ip a s output:" >> ${filename}
ip a s >> ${filename}

echo "--------------------------------------------" >> ${filename}
echo "ip r s output:" >> ${filename}
ip a s >> ${filename}

echo "that's it. EOF" >> ${filename}

:warning: warning: change the /srv/temp/ path above to some (existing!) path where you have external storage mounted. (I do have external SSD at /srv )

Then, restart turris, and I think at least one dump file should be generated.
After that, restart your upstream router to get new IPv6 prefix delegation from your ISP. (or just wait 24h depending how often ISP gives you new prefixes)

You should then have at least two files with detailed state of dhcpv6 client, interfaces and routing at the system.

(or not, because I did some major mistake. )

…to be clear, keep the data for yourself, they should stay private.
The tasks for you are: (using meld, diff or any other compare tool, compare the two - before and after - files)

  1. do you see the ipv6 change at eth1 (WAN)? (I expect yes)
  2. do you see the ipv6 change at br-lan (LAN)? (I have no idea, slightly expect no but I dunno)
  3. do you see the new prefix somewhere in the env part? (I hope yes)

Your little script is flawless, no worries (and yes, I use a USB memory mounted in /srv/…)
since you did not give the -o option in ip command it is difficult to read …
however:

  1. the change in eth2 is described in my initial article
  2. as described in my initial article: If valid_lft and preferred_lft times both become zero (EOL) the assigned address disappears after a few seconds and is replaced by nothing (my observation, 100% reproducible).
  3. as described in my initial article the new valid PD prefix is with eth2 but not with br-lan. No, I can not identify a valid PDaddress in br-lan without network restart. I do not think your nice little script did change anything but reporting the status in detail?!
    Did I use it the wrong way?
    I anonymized stuff so I think it is not risky to paste the diff here. For me it is difficult to read.
    It is the state before initiating the upstream router restart and the state after successful reconnect of the upstream router to the WAN including PD.
    Is this the right comparison?

ZZZ 1c1
ZZZ < dump from 2021_01_14_14-04-50
ZZZ —
ZZZ > dump from 2021_01_14_14-10-33
ZZZ 3,6c3,4
ZZZ < J_V_routes6=J_A4
ZZZ < J_T5_netmask=0
ZZZ < K_J_T6= target netmask gateway metric valid source
ZZZ < J_T6_gateway=fe80::ssss:eeee:rrrr:vvvv
ZZZ —
ZZZ > J_V_routes6=J_A5
ZZZ > K_J_T6= target netmask metric valid
ZZZ 8c6,8
ZZZ < RA_ADDRESSES=2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64,600,3600
ZZZ —
ZZZ > T_J_T10_valid=int
ZZZ > T_J_T11_metric=int
ZZZ > RA_ADDRESSES=fd00::aaaa:bbbb:cccc:dddd/64,0,3601 2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64,601,3601
ZZZ 11,12c11,13
ZZZ < J_T6_netmask=0
ZZZ < K_J_T7= target netmask metric valid
ZZZ —
ZZZ > J_T6_netmask=64
ZZZ > K_J_T7= target netmask gateway metric valid
ZZZ > J_T7_gateway=fe80::ssss:eeee:rrrr:vvvv
ZZZ 13a15,16
ZZZ > T_J_T11_valid=int
ZZZ > T_J_T12_metric=int
ZZZ 14a18
ZZZ > T_J_A2_2=object
ZZZ 18c22,23
ZZZ < J_V_ip6prefix=J_A10
ZZZ —
ZZZ > T_J_T10_target=string
ZZZ > T_J_T12_valid=int
ZZZ 20,22c25,26
ZZZ < PASSTHRU=00170010fd000000000000007effeeeerrrr0f7a005600102a010c23680f08007effeeeerrrr0f7a
ZZZ < T_J_A4_1=object
ZZZ < J_T8_netmask=56
ZZZ —
ZZZ > PASSTHRU=00170010fd000000000000007effeeeerrrr0f7a
ZZZ > J_T8_netmask=0
ZZZ 25,27c29,34
ZZZ < T_J_A4_2=object
ZZZ < J_T9_netmask=56
ZZZ < SERVER=fe80::ssss:eeee:rrrr:vvvv
ZZZ —
ZZZ > T_J_T11_target=string
ZZZ > T_J_A5_1=object
ZZZ > J_T9_netmask=0
ZZZ > K_J_T10= target netmask metric valid
ZZZ > T_J_T12_target=string
ZZZ > SERVER=
ZZZ 30,31c37,41
ZZZ < J_T3_valid=3600
ZZZ < T_J_A4_3=object
ZZZ —
ZZZ > J_T3_valid=3601
ZZZ > T_J_A5_2=object
ZZZ > J_T10_netmask=64
ZZZ > K_J_T11= target netmask gateway metric valid source
ZZZ > J_T11_gateway=fe80::ssss:eeee:rrrr:vvvv
ZZZ 34,45c44,58
ZZZ < J_T5_metric=384
ZZZ < T_J_A4_4=object
ZZZ < PROTO_IP6ADDR=2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64/600/3600/1/
ZZZ < J_T3_preferred=600
ZZZ < J_T5_valid=540
ZZZ < T_J_T5_source=string
ZZZ < J_T6_metric=384
ZZZ < T_J_A4_5=object
ZZZ < RA_ROUTES=::/0,fe80::ssss:eeee:rrrr:vvvv,540,384 2a01:c23:680f:800::/64,3600,256 2a01:c23:680f:800::/56,fe80::ssss:eeee:rrrr:vvvv,540,384
ZZZ < J_T6_valid=540
ZZZ < T_J_T6_source=string
ZZZ < J_T7_metric=256
ZZZ —
ZZZ > J_T4_valid=3601
ZZZ > T_J_A5_3=object
ZZZ > J_T11_netmask=56
ZZZ > K_J_T12= target netmask gateway metric valid source
ZZZ > J_T12_gateway=fe80::ssss:eeee:rrrr:vvvv
ZZZ > PROTO_IP6ADDR=fd00::aaaa:bbbb:cccc:dddd/64/0/3601/1/ 2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64/601/3601/1/
ZZZ > J_T3_preferred=0
ZZZ > J_T6_metric=256
ZZZ > T_J_A5_4=object
ZZZ > J_T12_netmask=56
ZZZ > RA_ROUTES=fd00::/64,3601,256 fd00::/64,fe80::ssss:eeee:rrrr:vvvv,541,512 ::/0,fe80::ssss:eeee:rrrr:vvvv,541,384 2a01:c22:bc47:ca00::/64,3601,256 2a01:c22:bc47:ca00::/56,fe80::ssss:e
eee:rrrr:vvvv,541,384
ZZZ > J_T4_preferred=601
ZZZ > J_T6_valid=3601
ZZZ > J_T7_metric=512
ZZZ > T_J_A5_5=object
ZZZ 47,49c60,61
ZZZ < PROTO_ROUTE6=::/0/fe80::ssss:eeee:rrrr:vvvv/384/540//2a01:c23:680f:8ff::/64 ::/0/fe80::ssss:eeee:rrrr:vvvv/384/540//2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64 2a01:c23:680f:800::/64//25
6/3600// 2a01:c23:680f:800::/56/fe80::ssss:eeee:rrrr:vvvv/384/540//2a01:c23:680f:8ff::/64 2a01:c23:680f:800::/56/fe80::ssss:eeee:rrrr:vvvv/384/540//2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64
ZZZ < J_T5_target=::
ZZZ < J_T7_valid=3600
ZZZ —
ZZZ > PROTO_ROUTE6=fd00::/64//256/3601// fd00::/64/fe80::ssss:eeee:rrrr:vvvv/512/541// ::/0/fe80::ssss:eeee:rrrr:vvvv/384/541//fd00::aaaa:bbbb:cccc:dddd/64 ::/0/fe80::ssss:eeee:rrrr:vvvv/38
4/541//2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64 2a01:c22:bc47:ca00::/64//256/3601// 2a01:c22:bc47:ca00::/56/fe80::ssss:eeee:rrrr:vvvv/384/541//fd00::aaaa:bbbb:cccc:dddd/64 2a01:c22:bc47:ca0
0::/56/fe80::ssss:eeee:rrrr:vvvv/384/541//2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64
ZZZ > J_T7_valid=541
ZZZ 51c63
ZZZ < T_J_A10_1=string
ZZZ —
ZZZ > T_J_A5_6=object
ZZZ 56,57c68,69
ZZZ < J_T6_target=::
ZZZ < J_T8_valid=540
ZZZ —
ZZZ > J_T6_target=fd00::
ZZZ > J_T8_valid=541
ZZZ 60c72
ZZZ < T_J_A11_1=string
ZZZ —
ZZZ > T_J_A5_7=object
ZZZ 62,63c74,76
ZZZ < J_T7_target=2a01:c23:680f:800::
ZZZ < J_T9_valid=540
ZZZ —
ZZZ > T_J_T4_mask=string
ZZZ > J_T7_target=fd00::
ZZZ > J_T9_valid=541
ZZZ 64a78
ZZZ > J_T10_metric=256
ZZZ 66c80,83
ZZZ < J_T8_target=2a01:c23:680f:800::
ZZZ —
ZZZ > J_T8_target=::
ZZZ > J_T10_valid=3601
ZZZ > J_T11_metric=384
ZZZ > T_J_A13_1=string
ZZZ 68c85,88
ZZZ < J_T9_target=2a01:c23:680f:800::
ZZZ —
ZZZ > J_T9_target=::
ZZZ > J_T11_valid=541
ZZZ > T_J_T11_source=string
ZZZ > J_T12_metric=384
ZZZ 70c90,94
ZZZ < J_T1_passthru=00170010fd000000000000007effeeeerrrr0f7a005600102a010c23680f08007effeeeerrrr0f7a
ZZZ —
ZZZ > J_T1_passthru=00170010fd000000000000007effeeeerrrr0f7a
ZZZ > J_A2_2=J_T4
ZZZ > J_T10_target=2a01:c22:bc47:ca00::
ZZZ > J_T12_valid=541
ZZZ > T_J_T12_source=string
ZZZ 74d97
ZZZ < OPTION_7=00
ZZZ 78,81c101,107
ZZZ < J_A4_1=J_T5
ZZZ < K_J_A2= 1
ZZZ < J_A4_2=J_T6
ZZZ < J_A4_3=J_T7
ZZZ —
ZZZ > J_T11_target=2a01:c22:bc47:ca00::
ZZZ > K_J_A2= 1 2
ZZZ > T_J_T4_ipaddr=string
ZZZ > T_J_T4_offlink=boolean
ZZZ > J_A5_1=J_T6
ZZZ > J_T12_target=2a01:c22:bc47:ca00::
ZZZ > J_A5_2=J_T7
ZZZ 84,85c110
ZZZ < K_J_A4= 1 2 3 4 5
ZZZ < J_A4_4=J_T8
ZZZ —
ZZZ > J_A5_3=J_T8
ZZZ 87,88c112,113
ZZZ < J_T5_source=2a01:c23:680f:8ff::/64
ZZZ < J_A4_5=J_T9
ZZZ —
ZZZ > K_J_A5= 1 2 3 4 5 6 7
ZZZ > J_A5_4=J_T9
ZZZ 90c115
ZZZ < J_T6_source=2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64
ZZZ —
ZZZ > J_A5_5=J_T10
ZZZ 93c118
ZZZ < J_A10_1=2a01:c23:680f:8ff::/64,487,3487
ZZZ —
ZZZ > J_A5_6=J_T11
ZZZ 95c120
ZZZ < PREFIXES=2a01:c23:680f:8ff::/64,487,3487
ZZZ —
ZZZ > PREFIXES=
ZZZ 97,98c122,123
ZZZ < J_T8_source=2a01:c23:680f:8ff::/64
ZZZ < J_A11_1=fd00::ssss:eeee:rrrr:vvvv
ZZZ —
ZZZ > J_T8_source=fd00::aaaa:bbbb:cccc:dddd/64
ZZZ > J_A5_7=J_T12
ZZZ 101,103c126,129
ZZZ < J_T9_source=2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64
ZZZ < K_J_A10= 1
ZZZ < K_J_A11= 1
ZZZ —
ZZZ > J_T4_mask=64
ZZZ > J_T9_source=2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64
ZZZ > J_A13_1=fd00::ssss:eeee:rrrr:vvvv
ZZZ > J_T11_source=fd00::aaaa:bbbb:cccc:dddd/64
ZZZ 105c131
ZZZ < K_J_V= action link_up data keep ip6addr routes6 ip6prefix dns interface
ZZZ —
ZZZ > K_J_V= action link_up data keep ip6addr routes6 dns interface
ZZZ 107,108c133,134
ZZZ < T_J_T5_gateway=string
ZZZ < J_V_dns=J_A11
ZZZ —
ZZZ > J_T12_source=2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64
ZZZ > J_V_dns=J_A13
ZZZ 110c136
ZZZ < J_T3_ipaddr=2a01:c23:680f:800:aaaa:bbbb:cccc:dddd
ZZZ —
ZZZ > J_T3_ipaddr=fd00::aaaa:bbbb:cccc:dddd
ZZZ 113,114c139
ZZZ < T_J_T5_netmask=string
ZZZ < T_J_T6_gateway=string
ZZZ —
ZZZ > K_J_A13= 1
ZZZ 115a141,142
ZZZ > J_T4_ipaddr=2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd
ZZZ > J_T4_offlink=1
ZZZ 116a144
ZZZ > T_J_T7_gateway=string
ZZZ 122d149
ZZZ < T_J_V_ip6prefix=array
ZZZ 127d153
ZZZ < OPTION_86=2a010c23680f08007effeeeerrrr0f7a
ZZZ 133c159,161
ZZZ < ADDRESSES= 2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64,600,3600
ZZZ —
ZZZ > T_J_T10_netmask=string
ZZZ > T_J_T11_gateway=string
ZZZ > ADDRESSES= fd00::aaaa:bbbb:cccc:dddd/64,0,3601 2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64,601,3601
ZZZ 135d162
ZZZ < PROTO_PREFIX6=2a01:c23:680f:8ff::/64,487,3487
ZZZ 138c165,167
ZZZ < T_J_T5_metric=int
ZZZ —
ZZZ > T_J_T4_valid=int
ZZZ > T_J_T11_netmask=string
ZZZ > T_J_T12_gateway=string
ZZZ 141d169
ZZZ < T_J_T5_valid=int
ZZZ 142a171,172
ZZZ > T_J_T12_netmask=string
ZZZ > T_J_T4_preferred=int
ZZZ 146d175
ZZZ < T_J_T5_target=string
ZZZ 148a178
ZZZ > K_J_T4= ipaddr mask preferred valid offlink
ZZZ 152,153d181
ZZZ < K_J_T5= target netmask gateway metric valid source
ZZZ < J_T5_gateway=fe80::ssss:eeee:rrrr:vvvv
ZZZ 155a184
ZZZ > T_J_T10_metric=int
ZZZ 176,177c205,208
ZZZ < inet6 2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64 scope global dynamic noprefixroute
ZZZ < valid_lft 3600sec preferred_lft 600sec
ZZZ —
ZZZ > inet6 2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64 scope global tentative dynamic noprefixroute
ZZZ > valid_lft 3601sec preferred_lft 601sec
ZZZ > inet6 fd00::aaaa:bbbb:cccc:dddd/64 scope global deprecated dynamic noprefixroute
ZZZ > valid_lft 3601sec preferred_lft 0sec
ZZZ 202,203c233,234
ZZZ < inet6 2a01:c23:680f:8ff::1/64 scope global dynamic noprefixroute
ZZZ < valid_lft 3487sec preferred_lft 487sec
ZZZ —
ZZZ > inet6 2a01:c23:680f:8ff::1/64 scope global deprecated dynamic noprefixroute
ZZZ > valid_lft 3145sec preferred_lft 0sec
ZZZ 236,237c267,270
ZZZ < inet6 2a01:c23:680f:800:aaaa:bbbb:cccc:dddd/64 scope global dynamic noprefixroute
ZZZ < valid_lft 3600sec preferred_lft 600sec
ZZZ —
ZZZ > inet6 2a01:c22:bc47:ca00:aaaa:bbbb:cccc:dddd/64 scope global tentative dynamic noprefixroute
ZZZ > valid_lft 3601sec preferred_lft 601sec
ZZZ > inet6 fd00::aaaa:bbbb:cccc:dddd/64 scope global deprecated dynamic noprefixroute
ZZZ > valid_lft 3601sec preferred_lft 0sec
ZZZ 262,263c295,296
ZZZ < inet6 2a01:c23:680f:8ff::1/64 scope global dynamic noprefixroute
ZZZ < valid_lft 3487sec preferred_lft 487sec
ZZZ —
ZZZ > inet6 2a01:c23:680f:8ff::1/64 scope global deprecated dynamic noprefixroute
ZZZ > valid_lft 3145sec preferred_lft 0sec

oki, so here we see the new prefix from dhcp6 client as environment variable.

Well, why not write something like the script below into /etc/odhcp6c.user. Read it first, understand it, perhaps change the echo into logger, check it with your setup and then uncomment the active commands (ip addr flush and ip addr add)

#!/bin/bash

target_iface="br-lan"
lan_network_size_bits="64"

old_prefix=$(ip -6 address show dev ${target_iface} | grep "scope global" | awk '{print $2}' | sed 's/::.*//')
echo "old: ${old_prefix}"

new_prefix=$(echo "${PROTO_PREFIX6}" | sed 's/::.*//')
echo "new: ${new_prefix}"

new_address="${new_prefix}::1/${lan_network_size_bits}"
echo ${new_address}

if [ -z "$PROTO_PREFIX6" ]; then
  echo "doing nothing, no prefix in env."
elif [ "$old_prefix" != "$new_prefix" ]; then
  echo "change the ips:"
  #uncomment as soon you'll realize the idea behind
#  ip -6 addr flush dev "$target_iface" scope global
#  ip -6 addr add "$new_address" dev "$target_iface"
else
  echo "no change in prefix."
fi

again, the credits should go here: https://wiki.debian.org/IPv6PrefixDelegation

second note - this script is super-unclean and one should do at least some basic sanitization before running this in production env.

yes, diff is not easy to read, try the “meld” tool I recommended above.

Hallo,

Thanks for your work!
Looks promising.

I had a quick look at it:
The script will flush the ULA and the PD-related GUA on br-lan, right?
I think I will try to change (limit) that part to GUA only.
It assumes the network part of the IP will not become abbreviated significantly. Well, I assume this is intended.
Then it creates a forged address from what is in PROTO_PREFIX6 at that moment.
Only 18 of my 60 log files display some PROTO_PREFIX6 at all. Probably before preferred_lft goes zero.
When address is set - routing follows automatically? I’m no expert in that area. Will probably work.
I did not analyze how and when env variable PROTO_PREFIX6 is created based on what.
Hence I wonder: There frequently are 2 valid prefixes in upstream eth2 available (in case of soft-reconnect). Will only the non-deprecated be used as a basis?
I try to do some investigation during foreseeable time. Will take me a while to look at the PROTO_PREFIX6 stuff.
Thanks a lot in advance.
Best Regards

The script will flush the ULA and the PD-related GUA on br-lan, right?

…yes. In my own networks designs I tend to do not use ULA so I here forgot to think about it. Yup, there should be some mechanism to backup the ULA and restore it after the flush, or, instead of flush, maybe directly use ip address delete XXXX dev XXXX to remove deprecated IP instead of ip address flush scope global doing flush of all global IPs including possible ULA(s).

It assumes the network part of the IP will not become abbreviated significantly.

…you’re right. Authors in concept [1] use ipv6calc or they call some bashish function fn_calc_ip6addr with limited features. I was not able to find ipv6calc in openwrt repos and copypasting the mentiond function would darken the concept. So cutting everything after ::, and appending 1instead was all the magic, working for random /60 prefix given to me by $my ISP.

Then it creates a forged address from what is in PROTO_PREFIX6 at that moment.

yup

Only 18 of my 60 log files display some PROTO_PREFIX6 at all. Probably before preferred_lft goes zero.

I did not analyze how and when env variable PROTO_PREFIX6 is created based on what.

from what I understood, the script is called multiple times on different reason- apparently they (reasons given by dhcp client) can be[2]:

  • bound
  • informed
  • updated
  • rebound
  • ra-updated
  • started

so I think PROTO_PREFIX6 is set only when relevant. (ra-updated, maybe updated?)
Perhaps extend the debug script with echo $@ to print all arguments as well… but my guess is that if there is no PROTO_PREFIX6, then there are no new prefixes for us to be changed.

Hence I wonder: There frequently are 2 valid prefixes in upstream eth2 available (in case of soft-reconnect). Will only the non-deprecated be used as a basis?

ough. here I have no clue, as I do not have any network with such a setup. I’d go indeed with the non-deprecated IP first (as I expect it will be dirty but it could work), but fully compliant solution should deal with the deprecated addresses as well.

I try to do some investigation during foreseeable time.

good luck and let us know here.

btw. this is default policy of your ISP to change the customer IPv6 ranges $everywhenever ?? I thought with IPv6 at least some weird workarounds (uPNP, port forwarding) known from IPv4 disappear, but this is like new class of “fun”…

cheers

[1] - https://wiki.debian.org/IPv6PrefixDelegation
[2] - https://github.com/openwrt/odhcp6c/blob/master/odhcp6c-example-script.sh