From: Michael Tremer Date: Tue, 23 Dec 2014 00:29:15 +0000 (+0000) Subject: Split port hooks in to (create|remove|up|down) actions X-Git-Tag: 007~60 X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Fnetwork.git;a=commitdiff_plain;h=1ba6a2bb3a8d7038e3e282bb82f44357de229643 Split port hooks in to (create|remove|up|down) actions The port hooks formerly had two functions that brought the device up or down. That caused some problems with hotplugging of the zones. Now the entire process has been split into four functions that every port hooks has to implement. create: Creates the device but does not bring it up yet. This will usually trigger a hotplug event so that various other port or zone hooks can attach the device or do similar actions. up: Essentially brings up the device, just like: ip link set devX up The action should propagate to any slave devices. down: Does essentially the opposite of "up" and should propagate to the slaves as well. remove: Removes any virtual devices and cleans up. This will also trigger a hotplug event so that all connected hooks will be notified about the removal. --- diff --git a/src/functions/functions.hook b/src/functions/functions.hook index 4c21f1ac..8146277b 100644 --- a/src/functions/functions.hook +++ b/src/functions/functions.hook @@ -22,8 +22,8 @@ HOOK_COMMANDS_CONFIG="hook_create hook_down hook_edit hook_status hook_remove" HOOK_COMMANDS_CONFIG="${HOOK_COMMANDS_CONFIG} hook_up" -HOOK_COMMANDS_PORT="hook_create hook_down hook_edit hook_hotplug \ - hook_hotplug_rename hook_info hook_status hook_up" +HOOK_COMMANDS_PORT="hook_new hook_edit hook_create hook_remove hook_up hook_down \ + hook_hotplug hook_hotplug_rename hook_info hook_status" HOOK_COMMANDS_ZONE="hook_add hook_create hook_discover hook_down hook_edit hook_help \ hook_info hook_remove hook_status hook_up hook_hotplug \ @@ -107,7 +107,7 @@ function hook_exec() { assert isset HOOK # Execute the requested command. - cmd "${hook_cmd}" "$@" + "${hook_cmd}" "$@" ) local ret=$? diff --git a/src/functions/functions.ports b/src/functions/functions.ports index 638d7ea1..5bed4d8b 100644 --- a/src/functions/functions.ports +++ b/src/functions/functions.ports @@ -111,7 +111,7 @@ function port_is_attached() { return ${EXIT_ERROR} } -function port_create() { +function port_new() { #local port=${1} #shift # @@ -134,7 +134,7 @@ function port_create() { # port_destroy ${port} #fi - hook_exec port ${hook} create $@ + hook_exec port ${hook} new $@ } function port_destroy() { @@ -180,8 +180,20 @@ function port_destroy() { rm -f $(port_file ${port}) } +function port_create() { + port_cmd "create" $@ +} + function port_remove() { - port_destroy $@ + local port="${1}" + assert isset port + + # If the device is still up, we need to bring it down first. + if device_is_up "${port}"; then + port_down "${port}" + fi + + port_cmd "remove" "${port}" } function port_edit() { diff --git a/src/functions/functions.settings b/src/functions/functions.settings index 2caa81fa..8b5ac98e 100644 --- a/src/functions/functions.settings +++ b/src/functions/functions.settings @@ -123,10 +123,10 @@ function settings_strip() { local var="$@" # Do nothing for strings that contain spaces. - if contains_spaces ${var}; then - print "${var}" - return ${EXIT_OK} - fi + #if contains_spaces ${var}; then + # print "${var}" + # return ${EXIT_OK} + #fi unquote "${var}" } diff --git a/src/functions/functions.zone b/src/functions/functions.zone index cad0b790..bf156dc9 100644 --- a/src/functions/functions.zone +++ b/src/functions/functions.zone @@ -730,6 +730,14 @@ function zone_ports_cmd() { done } +function zone_ports_create() { + zone_ports_cmd "port_create" $@ +} + +function zone_ports_remove() { + zone_ports_cmd "port_remove" $@ +} + function zone_ports_up() { zone_ports_cmd port_up $@ } diff --git a/src/header-port b/src/header-port index a26d8db2..80ff6940 100644 --- a/src/header-port +++ b/src/header-port @@ -72,3 +72,57 @@ function hook_status() { cli_device_headline "${port}" --long exit ${EXIT_OK} } + +# Create any virtual devices, but don't bring them up +# Must tolerate that the device may already exist +function hook_create() { + cmd_not_implemented +} + +# Must tolerate that the device may not exist +function hook_remove() { + cmd_not_implemented +} + +# Just bring up the device +function hook_default_up() { + local port="${1}" + assert isset port + + if ! device_exists "${port}"; then + log ERROR "Port '${port}' does not exist and cannot be brought up" + exit ${EXIT_ERROR} + fi + + # Bring up the port + device_set_up "${port}" + + # Bring up all slaves if the port has any + local slave + for slave in $(port_get_slaves "${port}"); do + port_up "${slave}" + done +} + +function hook_up() { + hook_default_up $@ +} + +function hook_default_down() { + local port="${1}" + assert isset port + + if device_exists "${port}"; then + device_set_down "${port}" + fi + + # Bring down all slaves if the port has any + local slave + for slave in $(port_get_slaves "${port}"); do + port_down "${slave}" + done +} + +function hook_down() { + hook_default_down $@ +} diff --git a/src/header-zone b/src/header-zone index 3241eb5a..996d0ac9 100644 --- a/src/header-zone +++ b/src/header-zone @@ -110,7 +110,7 @@ function hook_port_edit() { return ${EXIT_NOT_SUPPORTED} } -function hook_port_remove() { +function hook_port_destroy() { return ${EXIT_NOT_SUPPORTED} } @@ -122,6 +122,32 @@ function hook_port_status() { return ${EXIT_NOT_SUPPORTED} } +function hook_default_port_create() { + assert [ $# -ge 2 ] + + local zone="${1}" + local port="${2}" + + port_create "${port}" +} + +function hook_port_create() { + hook_default_port_create $@ +} + +function hook_default_port_remove() { + assert [ $# -ge 2 ] + + local zone="${1}" + local port="${2}" + + port_remove "${port}" +} + +function hook_port_remove() { + hook_default_port_remove $@ +} + function hook_port_up() { cmd_not_implemented } diff --git a/src/hooks/ports/batman-adv b/src/hooks/ports/batman-adv index 4dd1e9e8..99080cf5 100644 --- a/src/hooks/ports/batman-adv +++ b/src/hooks/ports/batman-adv @@ -33,7 +33,7 @@ function hook_check() { assert ismac ADDRESS } -function hook_create() { +function hook_new() { while [ $# -gt 0 ]; do case "${1}" in --address=*) @@ -94,39 +94,29 @@ function hook_edit() { exit ${EXIT_OK} } -function hook_up() { - local port=${1} +function hook_create() { + local port="${1}" assert isset port port_settings_read "${port}" ${HOOK_SETTINGS} - # Create batman device if it does not exist, yet. - if ! device_exists "${port}"; then - batman_adv_add "${port}" - fi + # Create a new batman-adv device + batman_adv_add "${port}" || exit ${?} # Set the address. device_set_address "${port}" "${ADDRESS}" - # Bring up the port - device_set_up "${port}" - exit ${EXIT_OK} } -function hook_down() { - local port=${1} +function hook_remove() { + local port="${1}" assert isset port - port_settings_read "${port}" - - local slave - for slave in ${SLAVES}; do - port_down "${slave}" - done + port_settings_read "${port}" ${HOOK_SETTINGS} - # Remove the batman device - device_exists "${port}" && batman_adv_delete "${port}" + # Remove the batman-adv device + batman_adv_delete "${port}" exit ${EXIT_OK} } @@ -137,24 +127,13 @@ function hook_hotplug() { case "$(hotplug_action)" in add) - # Don't handle this event if the batman - # device has not been started, yet. - #if ! device_exists "${port}"; then - # exit ${EXIT_NOT_HANDLED} - #fi - # Handle events of the same interface if hotplug_event_port_is_interface "${port}"; then - # Read configuration - port_settings_read "${port}" - # Bring up all slaves # They will be attached by their own hotplug event local slave - for slave in ${SLAVES}; do - if port_exists "${slave}"; then - port_up "${slave}" - fi + for slave in $(port_get_slaves "${port}"); do + port_create "${slave}" done exit ${EXIT_OK} @@ -162,28 +141,31 @@ function hook_hotplug() { # Handle slave devices that have just been created and # attach them. elif hotplug_event_interface_is_slave_of_port "${port}"; then - device_exists "${port}" || port_up "${port}" - batman_adv_attach "${port}" "${INTERFACE}" + + # If the batman-adv is already up, we will bring + # up the slave we just added as well. + if port_is_up "${port}"; then + port_up "${INTERFACE}" + fi fi exit ${EXIT_OK} ;; remove) - # Bring down all slaves when the batman device went down - local slave - for slave in ${SLAVES}; do - port_down "${slave}" - done - - exit ${EXIT_OK} - ;; + if hotplug_event_port_is_interface "${port}"; then + # Bring down all slaves when the batman device went down + local slave + for slave in $(port_get_slaves "${port}"); do + port_remove "${slave}" + done - *) - exit ${EXIT_NOT_HANDLED} + exit ${EXIT_OK} + fi ;; esac + exit ${EXIT_NOT_HANDLED} } function hook_status() { diff --git a/src/hooks/ports/bonding b/src/hooks/ports/bonding index 08041b99..817f6d0e 100644 --- a/src/hooks/ports/bonding +++ b/src/hooks/ports/bonding @@ -36,7 +36,7 @@ function hook_check() { assert isinteger MIIMON } -function hook_create() { +function hook_new() { hook_edit $@ } @@ -96,47 +96,122 @@ function hook_edit() { exit ${EXIT_OK} } -function hook_up() { - local device="${1}" - assert isset device +function hook_create() { + local port="${1}" + assert isset port - port_settings_read "${device}" ${HOOK_SETTINGS} + # Exit silently if the device already exists + device_exists "${port}" && exit ${EXIT_OK} - if ! device_exists ${device}; then - bonding_create "${device}" \ - --address="${ADDRESS}" \ - --mode="${MODE}" || exit ${EXIT_ERROR} + port_settings_read "${port}" ${HOOK_SETTINGS} + + # Create the bonding devices + bonding_create "${port}" \ + --address="${ADDRESS}" \ + --mode="${MODE}" || exit ${EXIT_ERROR} + + bonding_set_miimon "${port}" "${MIIMON}" + + exit ${EXIT_OK} +} + +function hook_remove() { + local port="${1}" + assert isset port + + port_settings_read "${port}" ${HOOK_SETTINGS} + + # Remove the bonding device + if device_exists "${port}"; then + bonding_remove "${port}" fi +} + +function hook_up() { + local port="${1}" + assert isset port - device_set_address "${device}" "${ADDRESS}" - bonding_set_miimon "${device}" "${MIIMON}" - device_set_up "${device}" + port_settings_read "${port}" ${HOOK_SETTINGS} + # Execute the default action + hook_default_up "${port}" + + # Bring up all slaves local slave for slave in $(unquote ${SLAVES}); do - if ! device_exists ${slave}; then - log WARNING "Cannot enslave '${slave}' to '${device}' as it is not available" - continue - fi - - bonding_enslave_device "${device}" "${slave}" + port_up "${slave}" done - - # Bring up the device. - device_set_up "${device}" - - exit ${EXIT_OK} } function hook_down() { - local device="${1}" + local port="${1}" + assert isset port - bonding_remove "${device}" + port_settings_read "${port}" ${HOOK_SETTINGS} + # Bring down all slaves local slave - for slave in ${SLAVES}; do - device_set_down "${slave}" + for slave in $(unquote ${SLAVES}); do + port_down "${slave}" done - exit ${EXIT_OK} + # Execute the default action + hook_default_down "${port}" +} + +function hook_hotplug() { + local port="${1}" + assert isset port + + case "$(hotplug_action)" in + add) + # Handle events of the same interface + if hotplug_event_port_is_interface "${port}"; then + # Read configuration + port_settings_read "${port}" ${HOOK_SETTINGS} + + # Bring up all slaves + # Attach those which already exist and try to create + # those which don't exist yet. They will be attached + # in their own hotplug event. + local slave + for slave in $(unquote ${SLAVES}); do + if device_exists "${slave}"; then + bonding_enslave_device "${port}" "${slave}" + else + port_create "${slave}" + fi + done + + exit ${EXIT_OK} + + # Handle slave devices that have just been created and + # attach them. + elif hotplug_event_interface_is_slave_of_port "${port}"; then + bonding_enslave_device "${port}" "${INTERFACE}" + + # If the parent device has been set up, we will + # bring up the slave device as well. + if device_is_up "${port}"; then + port_up "${INTERFACE}" + fi + fi + + exit ${EXIT_OK} + ;; + + remove) + if hotplug_event_port_is_interface "${port}"; then + # Bring down all slaves after the parent device went away + local slave + for slave in $(port_get_slaves "${port}"); do + port_remove "${slave}" + done + + exit ${EXIT_OK} + fi + ;; + esac + + exit ${EXIT_NOT_HANDLED} } diff --git a/src/hooks/ports/dummy b/src/hooks/ports/dummy index 41b830b5..df41ac9f 100644 --- a/src/hooks/ports/dummy +++ b/src/hooks/ports/dummy @@ -27,7 +27,7 @@ function hook_check() { assert ismac ADDRESS } -function hook_create() { +function hook_new() { while [ $# -gt 0 ]; do case "${1}" in --address=*) @@ -79,16 +79,30 @@ function hook_edit() { exit ${EXIT_OK} } -function hook_up() { - local port=${1} +function hook_create() { + local port="${1}" assert isset port + # Read configuration port_settings_read "${port}" ${HOOK_SETTINGS} - # Create device if not already exists. - if ! device_exists ${port}; then - dummy_create ${port} "${ADDRESS}" - fi + # Create the dummy device + dummy_create "${port}" "${ADDRESS}" + + exit ${EXIT_OK} +} + +function hook_remove() { + local port="${1}" + assert isset port + + # Remove the dummy device + dummy_remove "${port}" +} + +function hook_up() { + local port="${1}" + assert isset port # Bring up the port. device_set_up ${port} @@ -97,19 +111,12 @@ function hook_up() { } function hook_down() { - local port=${1} + local port="${1}" assert isset port - if ! device_exists ${port}; then - exit ${EXIT_OK} - fi - # Tear down the port. device_set_down ${port} - # Remove the dummy port. - dummy_remove ${port} - exit ${EXIT_OK} } diff --git a/src/hooks/ports/ethernet b/src/hooks/ports/ethernet index d0288466..fca74ae7 100644 --- a/src/hooks/ports/ethernet +++ b/src/hooks/ports/ethernet @@ -34,7 +34,7 @@ function hook_check() { fi } -function hook_create() { +function hook_new() { local port=${1} assert isset port shift @@ -47,36 +47,13 @@ function hook_create() { exit ${EXIT_OK} } -function hook_up() { - local port=${1} - assert isset port - - if ! device_exists "${port}"; then - log WARNING "Cannot bring up port '${port}' which does not exist" - exit ${EXIT_OK} - fi - - # Read in the confguration file. - port_settings_read "${port}" ${HOOK_SETTINGS} - - # Check if the MAC address is the right one. - if isset ADDRESS; then - device_set_address "${device}" "${ADDRESS}" - fi - - # Bring up the device. - device_set_up "${port}" - +function hook_create() { + # Nothing to do here. Real ethernet devices cannot + # be created. They are just there. exit ${EXIT_OK} } -function hook_down() { - local port=${1} - assert isset port - - # Set down the device. - device_set_down ${port} - +function hook_remove() { exit ${EXIT_OK} } diff --git a/src/hooks/ports/vlan b/src/hooks/ports/vlan index 5457c544..6ab0aecf 100644 --- a/src/hooks/ports/vlan +++ b/src/hooks/ports/vlan @@ -47,7 +47,7 @@ function hook_check() { done } -function hook_create() { +function hook_new() { while [ $# -gt 0 ]; do case "${1}" in --parent-device=*) @@ -97,37 +97,28 @@ function hook_edit() { exit ${EXIT_OK} } -function hook_up() { - local port=${1} +function hook_create() { + local port="${1}" assert isset port - if ! device_exists ${port}; then - # Read configuration file. - port_settings_read "${port}" ${HOOK_SETTINGS} + device_exists "${port}" && exit ${EXIT_OK} - vlan_create ${port} ${PARENT_DEVICE} ${TAG} ${ADDRESS} - fi + # Read configruation + port_settings_read "${port}" ${HOOK_SETTINGS} - # Bring up the device. - device_set_up ${port} + # Create the VLAN device + vlan_create "${port}" "${PARENT_DEVICE}" "${TAG}" "${ADDRESS}" exit ${EXIT_OK} } -function hook_down() { - local port=${1} +function hook_remove() { + local port="${1}" assert isset port - # Exit, if the port does not exist. - if ! device_exists ${port}; then - exit ${EXIT_OK} + if device_exists "${port}"; then + vlan_remove "${port}" fi - # Tear down the port. - device_set_down ${port} - - # Remove the port. - vlan_remove ${port} - exit ${EXIT_OK} } diff --git a/src/hooks/ports/wireless-adhoc b/src/hooks/ports/wireless-adhoc index 515c9057..1544473c 100644 --- a/src/hooks/ports/wireless-adhoc +++ b/src/hooks/ports/wireless-adhoc @@ -114,6 +114,41 @@ function hook_edit() { exit ${EXIT_OK} } +function hook_create() { + local port="${1}" + assert isset port + + device_exists "${port}" && exit ${EXIT_OK} + + port_settings_read "${port}" ${HOOK_SETTINGS} + + # Check if the PHY is present. + local phy="$(phy_get "${PHY}")" + if ! isset phy; then + log DEBUG "phy '${PHY}' is not present" + exit ${EXIT_ERROR} + fi + + # Create the wireless device, if it does not exist, yet. + wireless_create "${port}" \ + --address="${ADDRESS}" \ + --phy="${phy}" \ + --type="ibss" + + exit ${EXIT_OK} +} + +function hook_remove() { + local port="${1}" + assert isset port + + if device_exists "${port}"; then + wireless_remove "${port}" + fi + + exit ${EXIT_OK} +} + function hook_up() { local port=${1} assert isset port @@ -148,9 +183,6 @@ function hook_down() { # Leave the ad-hoc network. wireless_ibss_leave "${port}" - # Remove the device if it is still present. - wireless_remove "${port}" - exit ${EXIT_OK} } diff --git a/src/hooks/ports/wireless-ap b/src/hooks/ports/wireless-ap index 4983f9c2..8de0aba3 100644 --- a/src/hooks/ports/wireless-ap +++ b/src/hooks/ports/wireless-ap @@ -53,7 +53,7 @@ function hook_check() { fi } -function hook_create() { +function hook_new() { while [ $# -gt 0 ]; do case "${1}" in --broadcast-ssid=*) @@ -139,10 +139,12 @@ function hook_edit() { exit ${EXIT_OK} } -function hook_up() { - local port=${1} +function hook_create() { + local port="${1}" assert isset port + device_exists "${port}" && exit ${EXIT_OK} + port_settings_read "${port}" ${HOOK_SETTINGS} # Check if the PHY is present. @@ -152,26 +154,17 @@ function hook_up() { exit ${EXIT_ERROR} fi - # Create the wireless device, if it does not exist, yet. - if ! device_exists ${port}; then - wireless_create ${port} --phy="${phy}" --type="ap" \ - --address="${ADDRESS}" - fi - - # Start the hostapd service. - #hostapd_start ${port} - local ret=$? - - if [ ${ret} -ne ${EXIT_OK} ]; then - log ERROR "Could not start hostapd on port '${port}': ${ret}" - exit ${EXIT_ERROR} - fi + # Create the wireless device + wireless_create "${port}" \ + --phy="${phy}" \ + --type="ap" \ + --address="${ADDRESS}" exit ${EXIT_OK} } -function hook_down() { - local port=${1} +function hook_remove() { + local port="${1}" assert isset port # Remove the device if present @@ -182,19 +175,34 @@ function hook_down() { exit ${EXIT_OK} } +function hook_up() { + local port="${1}" + assert isset port + + # The port must already exist before + # hostapd is started. Otherwise it will + # fail horribly over and over again. + assert device_exists "${port}" + + hostapd_start "${port}" +} + +function hook_down() { + local port="${1}" + assert isset port + + hostapd_stop "${port}" +} + function hook_hotplug() { local port="${1}" assert isset port case "$(hotplug_action)" in add) - # Start hostapd after the port has been brought up - if hotplug_event_port_is_interface "${port}"; then - hostapd_start "${port}" - - # Bring up the port when the phy is plugged in - elif hotplug_event_port_uses_phy "${port}"; then - hook_up "${port}" + # Create the port when the phy is plugged in + if hotplug_event_port_uses_phy "${port}"; then + hook_create "${port}" fi ;; @@ -202,13 +210,11 @@ function hook_hotplug() { # Stop hostapd if hotplug_event_port_is_interface "${port}"; then hostapd_stop "${port}" - fi - ;; - *) - exit ${EXIT_NOT_HANDLED} + exit ${EXIT_OK} + fi ;; esac - exit ${EXIT_OK} + exit ${EXIT_NOT_HANDLED} } diff --git a/src/hooks/zones/bridge b/src/hooks/zones/bridge index d72564a7..021e4402 100644 --- a/src/hooks/zones/bridge +++ b/src/hooks/zones/bridge @@ -123,6 +123,7 @@ function hook_up() { device_set_promisc "${zone}" on # Bring up all ports + zone_ports_create "${zone}" zone_ports_up "${zone}" # Bring up all configurations @@ -175,6 +176,7 @@ function hook_down() { # Bring down all the ports. zone_ports_down "${zone}" + zone_ports_remove "${zone}" # Remove the bridge. device_set_down "${zone}" @@ -291,7 +293,7 @@ function hook_port_edit() { exit ${EXIT_OK} } -function hook_port_remove() { +function hook_port_destroy() { assert [ $# -eq 2 ] local zone="${1}" @@ -336,7 +338,7 @@ function hook_port_up() { # TODO Apply priority (#10609) # Make sure that the port is up - device_set_up "${port}" + port_up "${port}" exit ${EXIT_OK} } diff --git a/src/network b/src/network index 1999c3d5..eccf2f43 100644 --- a/src/network +++ b/src/network @@ -468,22 +468,9 @@ function cli_port() { action=${2} shift 2 - # Action aliases - case "${action}" in - start) - action="up" - ;; - stop) - action="down" - ;; - show) - action="status" - ;; - esac - case "${action}" in - edit|up|down|status) - port_${action} ${port} $@ + edit|create|remove|up|down|status) + port_${action} "${port}" $@ ;; *) error "Unrecognized argument: ${action}" @@ -495,7 +482,7 @@ function cli_port() { shift case "${action}" in - create|destroy) + new|destroy) port_${action} $@ ;; *) @@ -1053,7 +1040,7 @@ function cli_reset() { local port for port in $(ports_get --all); do - port_remove ${port} + port_destroy "${port}" done # Flush all DNS servers. diff --git a/src/udev/network-hotplug b/src/udev/network-hotplug index 21dc4dd7..a738970a 100644 --- a/src/udev/network-hotplug +++ b/src/udev/network-hotplug @@ -82,7 +82,7 @@ case "${SUBSYSTEM}" in add,ethernet) # Create a default port for all ethernet devices if ! port_exists "${INTERFACE}"; then - port_create "ethernet" "${INTERFACE}" + port_new "ethernet" "${INTERFACE}" exit ${EXIT_OK} fi ;;