. /usr/lib/network/header-port
-HOOK_SETTINGS="HOOK ADDRESS MIIMON MODE SLAVES"
+HOOK_SETTINGS=(
+ "ADDRESS"
+ "MIIMON"
+ "MODE"
+ "OFFLOADING"
+ "SLAVES"
+)
-ADDRESS=$(mac_generate)
-SLAVES=""
-MIIMON=100
+DEFAULT_MIIMON=100
+DEFAULT_MODE="balance-rr"
-function hook_check() {
+hook_check_settings() {
assert isset ADDRESS
assert ismac ADDRESS
assert isinteger MIIMON
}
-function hook_create() {
- _edit $@
-}
-
-function hook_edit() {
- local port=${1}
- assert isset port
- shift
-
+hook_parse_cmdline() {
while [ $# -gt 0 ]; do
case "${1}" in
--address=*)
- ADDRESS=$(cli_get_val ${1})
+ ADDRESS="$(cli_get_val "${1}")"
+
+ if ! mac_is_valid "${ADDRESS}"; then
+ error "Invalid MAC address: ${ADDRESS}"
+ return ${EXIT_ERROR}
+ fi
;;
+
--miimon=*)
- MIIMON=$(cli_get_val ${1})
+ MIIMON=$(cli_get_val "${1}")
;;
--mode=*)
- MODE=$(cli_get_val ${1})
+ MODE=$(cli_get_val "${1}")
;;
- --slave=*)
- slave=$(cli_get_val ${1})
- SLAVES="${SLAVES} ${slave}"
+ --offloading=*)
+ OFFLOADING="$(cli_get_val "${1}")"
+
+ if enabled OFFLOADING; then
+ OFFLOADING="on"
+ elif disabled OFFLOADING; then
+ OFFLOADING="off"
+ else
+ error "Invalid value for offloading: ${OFFLOADING}"
+ return ${EXIT_ERROR}
+ fi
+ ;;
+ +*)
+ local slave=$(cli_get_val "${1:1}")
+
+ if port_exists "${slave}"; then
+ if list_match "${slave}" ${SLAVES}; then
+ warning "Port ${slave} is already enslaved"
+ else
+ list_append SLAVES "${slave}"
+ fi
+ else
+ warning "Port ${slave} does not exist"
+ fi
+ ;;
+ -*)
+ local slave=$(cli_get_val "${1:1}")
+ if ! list_remove SLAVES "${slave}"; then
+ warning "Port ${slave} is not a slave of this bonding device"
+ fi
;;
*)
warning "Unknown argument '${1}'"
shift
done
- DEVICE=${port}
+ if isset ADDRESS; then
+ if ! ismac ADDRESS; then
+ error "The given MAC address is invalid: ${ADDRESS}"
+ return ${EXIT_ERROR}
+ fi
+ else
+ ADDRESS=$(mac_generate)
+ fi
+}
+
+hook_new() {
+ if ! hook_parse_cmdline "$@"; then
+ return ${EXIT_ERROR}
+ fi
+
+ # Find a new name
+ local port=$(port_find_free ${BONDING_PORT_PATTERN})
+ assert isset port
- # XXX think this must move to _check()
- if ! isset DEVICE; then
- error "You must set a device name."
- exit ${EXIT_ERROR}
+ # Save configuration
+ if port_settings_write "${port}" ${HOOK_SETTINGS[*]}; then
+ log INFO "New port ${port} has been created"
+ else
+ error "Could not save configuration for ${port}"
+ return ${EXIT_ERROR}
fi
- if ! isset SLAVES; then
- error "You need to specify at least one slave port (e.g. --slave=port0)."
- exit ${EXIT_ERROR}
+ return ${EXIT_OK}
+}
+
+hook_edit() {
+ local port=${1}
+
+ if ! hook_default_edit "$@"; then
+ return ${EXIT_ERROR}
fi
- local slave
- for slave in $(unquote ${SLAVES}); do
- if ! device_is_ethernet ${slave}; then
- error "Slave device '${slave}' is not an ethernet device."
- exit ${EXIT_ERROR}
+ # If the master device is up, make sure that all
+ # slaves are up, too
+ if device_exists "${port}"; then
+ # Setting the mode requires us to destroy the device
+ # and to recreate it again.
+ local mode=$(bonding_get_mode "${port}")
+ if [ "${mode}" != "${MODE}" ]; then
+ port_restart "${port}"
+ return ${EXIT_OK}
fi
- done
- # Remove any whitespace
- SLAVES=$(echo ${SLAVES})
+ # Set address
+ device_set_address "${port}" "${ADDRESS}"
- port_config_write ${port} ${HOOK_SETTINGS}
+ # Set miimon
+ bonding_set_miimon "${port}" "${MIIMON}"
- exit ${EXIT_OK}
+ local slave
+ for slave in ${SLAVES}; do
+ if device_exists "${slave}"; then
+ bonding_enslave_device "${port}" "${slave}"
+ else
+ port_create "${slave}"
+ fi
+ done
+ fi
}
-function hook_up() {
- local device=${1}
- assert isset device
+hook_create() {
+ local port="${1}"
+ assert isset port
+
+ # Exit silently if the device already exists
+ device_exists "${port}" && exit ${EXIT_OK}
- port_config_read ${device}
+ port_settings_read "${port}" ${HOOK_SETTINGS[*]}
- if device_exists ${device}; then
- log DEBUG "Bonding device '${device}' does already exist."
+ # Create the bonding devices
+ bonding_create "${port}" \
+ --address="${ADDRESS}" \
+ --mode="${MODE}" || exit ${EXIT_ERROR}
- device_set_address ${device} ${ADDRESS}
- device_set_up ${device}
+ bonding_set_miimon "${port}" "${MIIMON}"
- exit ${EXIT_OK}
+ exit ${EXIT_OK}
+}
+
+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
+}
- bonding_create ${device} --address="${ADDRESS}" --mode="${MODE}"
- local ret=$?
+hook_up() {
+ local port="${1}"
+ assert isset port
- [ ${ret} -eq ${EXIT_OK} ] || exit ${EXIT_ERROR}
+ port_settings_read "${port}" ${HOOK_SETTINGS[*]}
- bonding_set_miimon ${device} ${MIIMON}
- device_set_up ${device}
+ # Auto-enable or disable hardware offloading
+ if ! isset OFFLOADING || enabled OFFLOADING; then
+ offloading_auto "${port}"
+ else
+ offloading_disable_all "${port}"
+ fi
+ # 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
- warning_log "${device}: configured slave '${slave}' 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}
+hook_down() {
+ 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}"
+}
+
+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}
}