Skip to content

Commit

Permalink
[pd] deprecate old prefixes in radvd configuration on DHCPv6 PD change (
Browse files Browse the repository at this point in the history
#2701)

This commit addresses an issue where old prefixes were not being
properly deprecated in the RADVD configuration when the upstream
interface's delegated prefix changed. Previously, only the new prefix
would be advertised, potentially leading to issues for OT still using
the old prefix.

Now, upon a new PD message, dhcpcd.enter-hook will:

- Identify the old and new prefixes: It retrieves the old and new
  prefix information from the dhcpcd environment variables.

- Configure radvd to deprecate the old prefix: If an old prefix exists
  and is different from the new prefix, the radvd.conf file is updated
  to include the old prefix with a preferred and valid lifetime of
  0. This signals to OT that the prefix is deprecated and should no
  longer be used.

- Publish the new prefix: The new prefix is added to radvd.conf with
  the appropriate lifetimes received from the DHCPv6 server.

- Reload radvd: The radvd service is reloaded to apply the changes.
  • Loading branch information
yangsong-cnyn authored Feb 26, 2025
1 parent 1e20da3 commit 6868d1a
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
62 changes: 51 additions & 11 deletions script/reference-device/dhcpcd.enter-hook
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,66 @@ WPAN_INTERFACE="wpan0"
RADVD_CONF="/etc/radvd.conf"
LOG_TAG="dhcpcd.enter.hook:"


config_ra()
{
local old_prefix="$1"
local old_prefix_len="$2"
local new_prefix="$3"
local new_prefix_len="$4"
local new_pltime="$5"
local new_vltime="$6"

local deprecate_old_prefix=false
if [ -n "$old_prefix" ] && [ "$old_prefix/$old_prefix_len" != "$new_prefix/$new_prefix_len" ]; then
deprecate_old_prefix=true
fi

local publish_new_prefix=false
if [ -n "$new_prefix" ] && [ -n "$new_prefix_len" ] && [ -n "$new_pltime" ] && [ -n "$new_vltime" ]; then
publish_new_prefix=true
fi

logger "$LOG_TAG $reason start config radvd"

sudo tee "${RADVD_CONF}" > /dev/null <<EOF
interface ${WPAN_INTERFACE}
{
IgnoreIfMissing on;
AdvSendAdvert on;
prefix ${1}/${2}
EOF

if "$deprecate_old_prefix"; then
logger "$LOG_TAG Deprecating old prefix $old_prefix/$old_prefix_len"
sudo tee -a "${RADVD_CONF}" > /dev/null <<EOF
prefix ${old_prefix}/${old_prefix_len}
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
AdvPreferredLifetime 0;
AdvValidLifetime 0;
};
EOF
fi

if $publish_new_prefix; then
logger "$LOG_TAG Publishing new prefix $new_prefix/$new_prefix_len PLTime: $new_pltime VLTime: $new_vltime"
sudo tee -a "${RADVD_CONF}" > /dev/null <<EOF
prefix ${new_prefix}/${new_prefix_len}
{
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
AdvPreferredLifetime ${3};
AdvValidLifetime ${4};
AdvPreferredLifetime ${new_pltime};
AdvValidLifetime ${new_vltime};
};
EOF
fi

sudo tee -a "${RADVD_CONF}" > /dev/null <<EOF
};
EOF

}


Expand All @@ -63,17 +103,17 @@ if [ ${interface} = ${UPSTREAM_INTERFACE} ]; then
# Split the variable into name and value
name="${var%%=*}"
value="${var#*=}"
logger -t "$LOG_TAG $reason sysenv: " "$name=$value"
logger "$LOG_TAG $reason sysenv: $name=$value"
done

case $reason in
DELEGATED6 | REBIND6 | RENEW6 | BOUND6 )
if [ -z "$new_dhcp6_ia_pd1_prefix1" ] || [ -z "$new_dhcp6_ia_pd1_prefix1_length" ] || \
[ -z "$new_dhcp6_ia_pd1_prefix1_pltime" ] || [ -z "$new_dhcp6_ia_pd1_prefix1_vltime" ]; then
logger "$LOG_TAG WARNING: Missing DHCPv6 prefix information. Skipping radvd configuration."
else
logger "$LOG_TAG prefix is $new_dhcp6_ia_pd1_prefix1 length is $new_dhcp6_ia_pd1_prefix1_length pltime is $new_dhcp6_ia_pd1_prefix1_pltime vltime is $new_dhcp6_ia_pd1_prefix1_vltime"
config_ra $new_dhcp6_ia_pd1_prefix1 $new_dhcp6_ia_pd1_prefix1_length $new_dhcp6_ia_pd1_prefix1_pltime $new_dhcp6_ia_pd1_prefix1_vltime
# TODO: Handle multiple IA_PD prefixes (new_dhcp6_ia_pd{i}_prefix{j}, new_dhcp6_ia_pd{i}_prefix{j}_length, etc.)
# and deprecate old prefixes properly for each. Currently, only one prefix is handled.
if { [ -n "$new_dhcp6_ia_pd1_prefix1" ] && [ -n "$new_dhcp6_ia_pd1_prefix1_length" ]; } || \
{ [ -n "$old_dhcp6_ia_pd1_prefix1" ] && [ -n "$old_dhcp6_ia_pd1_prefix1_length" ]; }; then
config_ra "$old_dhcp6_ia_pd1_prefix1" "$old_dhcp6_ia_pd1_prefix1_length" \
"$new_dhcp6_ia_pd1_prefix1" "$new_dhcp6_ia_pd1_prefix1_length" "$new_dhcp6_ia_pd1_prefix1_pltime" "$new_dhcp6_ia_pd1_prefix1_vltime"
if systemctl is-active network.target; then
sudo systemctl reload-or-restart radvd || logger "$LOG_TAG Failed to reload radvd"
fi
Expand Down
4 changes: 3 additions & 1 deletion script/reference-device/dhcpcd.exit-hook
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ if [ ${interface} = ${UPSTREAM_INTERFACE} ]; then
done

case $reason in
EXPIRE6 | STOP6)
EXPIRE6 | STOP6 | RELEASE6 )
# TODO: Handle multiple IA_PD prefixes (new_dhcp6_ia_pd{i}_prefix{j}, new_dhcp6_ia_pd{i}_prefix{j}_length, etc.)
# and deprecate old prefixes properly for each. Currently, only one prefix is handled.)
if [ -z "$old_dhcp6_ia_pd1_prefix1" ] || [ -z "$old_dhcp6_ia_pd1_prefix1_length" ]; then
logger "$LOG_TAG WARNING: Missing DHCPv6 prefix information. Skipping radvd configuration."
else
Expand Down

0 comments on commit 6868d1a

Please sign in to comment.