Skip to content

Commit

Permalink
Add pd daemon service: naming and comment improment
Browse files Browse the repository at this point in the history
  • Loading branch information
yangsong-cnyn committed Nov 5, 2024
1 parent cb53771 commit a3033df
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 57 deletions.
34 changes: 18 additions & 16 deletions script/_dhcpv6_pd_ref
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,35 @@ PD_DAEMON_PATH="${PD_DAEMON_DIR}/dhcp6_pd_daemon.py"
PD_DAEMON_SERVICE_NAME="dhcp6_pd_daemon.service"
PD_DAEMON_SERVICE_PATH="/etc/systemd/system/${PD_DAEMON_SERVICE_NAME}"

DHCP_CONFIG_FILE="/etc/dhcpcd.conf.orig"
DHCP_CONFIG_ORIG_FILE="/etc/dhcpcd.conf.orig"
DHCP_CONFIG_WITH_PD_FILE="/etc/dhcpcd.conf.with-pd"
DHCP_CONFIG_NO_PD_FILE="/etc/dhcpcd.conf.no-pd"
DHCP_CONFIG_PATH="/etc/dhcpcd.conf"
DHCP_CONFIG_ORIG_PATH="/etc/dhcpcd.conf.orig"
DHCP_CONFIG_PD_PATH="/etc/dhcpcd.conf.pd"
DHCP_CONFIG_NO_PD_PATH="/etc/dhcpcd.conf.no-pd"

# Create dhcpcd configuration file with ipv6 prefix request.
create_dhcpcd_conf_with_pd()
create_dhcpcd_conf_pd()
{
sudo tee ${DHCP_CONFIG_WITH_PD_FILE} >/dev/null <<EOF
sudo tee ${DHCP_CONFIG_PD_PATH} >/dev/null <<EOF
noipv6rs # disable router solicitation
interface eth0
iaid 1
ia_pd 2/::/64 -
release
# Disable Router Solicitations (RS) again, specifically for eth0.
# This ensures that accept_ra is prevented from being set to 0, allowing
# the interface to accepting Router Advertisements and configuring IPv6
# based on them. The exact reason for requiring 'noipv6rs' twice
# is not fully understood but has been observed to be necessary through
# experimentation.
noipv6rs
EOF
}

# Create dhcpcd configuration file with no prefix request.
create_dhcpcd_conf_no_pd()
{
sudo tee ${DHCP_CONFIG_NO_PD_FILE} >/dev/null <<EOF
sudo tee ${DHCP_CONFIG_NO_PD_PATH} >/dev/null <<EOF
noipv6rs # disable router solicitation
interface eth0
iaid 1
release
noipv6rs
EOF
}

Expand Down Expand Up @@ -97,8 +99,8 @@ dhcpv6_pd_ref_uninstall()
sudo rm -f ${PD_DAEMON_SERVICE_PATH} || true
fi

if [[ -f ${DHCP_CONFIG_ORIG_FILE} ]]; then
sudo mv ${DHCP_CONFIG_ORIG_FILE} ${DHCP_CONFIG_FILE}
if [[ -f ${DHCP_CONFIG_ORIG_PATH} ]]; then
sudo mv ${DHCP_CONFIG_ORIG_PATH} ${DHCP_CONFIG_PATH}
fi

sudo rm -f ${DHCPCD_ENTER_HOOK} ${DHCPCD_EXIT_HOOK}
Expand All @@ -117,8 +119,8 @@ dhcpv6_pd_ref_install()
{
with DHCPV6_PD_REF || return 0

if [[ -f ${DHCP_CONFIG_FILE} ]]; then
sudo mv ${DHCP_CONFIG_FILE} ${DHCP_CONFIG_ORIG_FILE}
if [[ -f ${DHCP_CONFIG_PATH} ]]; then
sudo mv ${DHCP_CONFIG_PATH} ${DHCP_CONFIG_ORIG_PATH}
fi

# Add dhcpcd.hooks
Expand All @@ -127,7 +129,7 @@ dhcpv6_pd_ref_install()
sudo mkdir -p ${PD_DAEMON_DIR}
sudo install -m 755 "$(dirname "$0")"/reference-device/dhcp6_pd_daemon.py ${PD_DAEMON_PATH}

create_dhcpcd_conf_with_pd
create_dhcpcd_conf_pd
create_dhcpcd_conf_no_pd
create_dhcp6_pd_daemon_service

Expand Down
81 changes: 41 additions & 40 deletions script/reference-device/dhcp6_pd_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,49 +42,42 @@
bus = dbus.SystemBus()
intended_dhcp6pd_state = None

DHCP_CONFIG_FILE = "/etc/dhcpcd.conf"
DHCP_CONFIG_WITH_PD_FILE = "/etc/dhcpcd.conf.with-pd"
DHCP_CONFIG_NO_PD_FILE = "/etc/dhcpcd.conf.no-pd"
DHCP_CONFIG_PATH = "/etc/dhcpcd.conf"
DHCP_CONFIG_PD_PATH = "/etc/dhcpcd.conf.pd"
DHCP_CONFIG_NO_PD_PATH = "/etc/dhcpcd.conf.no-pd"

def restart_dhcpcd_service(config_path):
if not os.path.isfile(config_path):
logging.error(f"{config_path} not found. Cannot apply configuration.")
return
try:
subprocess.run(["sudo", "cp", config_path, DHCP_CONFIG_PATH], check=True)
subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
subprocess.run(["sudo", "service", "dhcpcd", "restart"], check=True)
logging.info(f"Successfully restarted dhcpcd service with {config_path}.")
except subprocess.CalledProcessError as e:
logging.error(f"Error restarting dhcpcd service: {e}")

def restart_dhcpcd_with_pd_config():
global intended_dhcp6pd_state
if os.path.isfile(DHCP_CONFIG_WITH_PD_FILE):
try:
subprocess.run(["sudo", "cp", DHCP_CONFIG_WITH_PD_FILE, DHCP_CONFIG_FILE], check=True)
subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
subprocess.run(["sudo", "service", "dhcpcd", "restart"], check=True)
logging.info("Successfully restarted dhcpcd service with pd enabled.")
intended_dhcp6pd_state = None
except subprocess.CalledProcessError as e:
logging.error(f"Error restarting dhcpcd service: {e}")
intended_dhcp6pd_state = None
else:
logging.error(f"{DHCP_CONFIG_WITH_PD_FILE} not found. Cannot apply configuration with pd enabled.")
intended_dhcp6pd_state = None

def restore_default_config():
if os.path.isfile(DHCP_CONFIG_NO_PD_FILE):
try:
subprocess.run(["sudo", "cp", DHCP_CONFIG_NO_PD_FILE, DHCP_CONFIG_FILE], check=True)
subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
subprocess.run(["sudo", "service", "dhcpcd", "restart"], check=True)
logging.info("Successfully restarted dhcpcd service with pd disabled.")
except subprocess.CalledProcessError as e:
logging.error(f"Error restarting dhcpcd service: {e}")
else:
logging.error(f"{DHCP_CONFIG_NO_PD_FILE} not found. Cannot apply configuration with pd disabled.")
restart_dhcpcd_service(DHCP_CONFIG_PD_PATH)
intended_dhcp6pd_state = None

def restart_dhcpcd_with_no_pd_config():
restart_dhcpcd_service(DHCP_CONFIG_NO_PD_PATH)

def properties_changed_handler(interface_name, changed_properties, invalidated_properties):
global intended_dhcp6pd_state
if "Dhcp6PdState" in changed_properties:
new_state = changed_properties["Dhcp6PdState"]
logging.info(f"Dhcp6PdState changed to: {new_state}")
if new_state == "running" and intended_dhcp6pd_state != "running":
intended_dhcp6pd_state = "running"
thread = threading.Thread(target=restart_dhcpcd_with_pd_config)
thread.start()
elif new_state in ("stopped", "disabled") and intended_dhcp6pd_state is None:
restore_default_config()
if "Dhcp6PdState" not in changed_properties:
return
new_state = changed_properties["Dhcp6PdState"]
logging.info(f"Dhcp6PdState changed to: {new_state}")
if new_state == "running" and intended_dhcp6pd_state != "running":
intended_dhcp6pd_state = "running"
thread = threading.Thread(target=restart_dhcpcd_with_pd_config)
thread.start()
elif new_state in ("stopped", "disabled") and intended_dhcp6pd_state is None:
restart_dhcpcd_with_no_pd_config()

def connect_to_signal():
try:
Expand All @@ -99,11 +92,19 @@ def connect_to_signal():

def check_and_reconnect(dbus_obj, properties_dbus_iface):
if dbus_obj is None:
dbus_obj, properties_dbus_iface = connect_to_signal()
connect_to_signal()

def main():
# Ensure dhcpcd is running in its last known state. In case it was killed or crashed previously, or
# radvd is not yet enabled because of inactive network.target
# Ensure dhcpcd is running in its last known state. This addresses a potential race condition
# during system startup due to the loop dependency in dhcpcd-radvd-network.target.
#
# - network.target activation relies on the completion of dhcpcd start
# - during bootup, dhcpcd tries to start radvd with PD enabled before network.target is
# active, which leads to a timeout failure
# - so we will prevent radvd from starting before target.network is active
#
# By restarting dhcpcd here, we ensure it runs after network.target is active, allowing
# radvd to start correctly and dhcpcd to configure the interface.
try:
subprocess.run(["sudo", "systemctl", "reload-or-restart", "dhcpcd"], check=True)
logging.info("Successfully restarting dhcpcd service.")
Expand Down
1 change: 0 additions & 1 deletion script/reference-device/dhcpcd.exit-hook
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,3 @@ if [ ${interface} = ${UPSTREAM_INTERFACE} ]; then
;;
esac
fi

0 comments on commit a3033df

Please sign in to comment.