# Set device up
device_set_up() {
- local device=${1}
+ assert [ $# -eq 1 ]
- # Silently fail if device was not found
- [ -z "${device}" ] && return ${EXIT_ERROR}
+ local device=${1}
# Do nothing if device is already up
device_is_up ${device} && return ${EXIT_OK}
+ log INFO "Bringing up ${device}"
+
device_set_parent_up ${device}
+ if ! cmd ip link set ${device} up; then
+ return ${EXIT_ERROR}
+ fi
- log DEBUG "Setting up device '${device}'"
+ # Set SMP affinity
+ if interrupt_use_smp_affinity; then
+ device_auto_configure_smp_affinity "${port}"
+ fi
- ip link set ${device} up
+ return ${EXIT_OK}
}
device_set_parent_up() {
# Set device down
device_set_down() {
- local device=${1}
- assert isset device
+ assert [ $# -eq 1 ]
+ local device=${1}
local ret=${EXIT_OK}
if device_is_up ${device}; then
- log DEBUG "Tearing down device '${device}'"
+ log INFO "Bringing down ${device}"
- ip link set ${device} down
+ cmd ip link set ${device} down
ret=$?
fi
device_get_mtu() {
local device=${1}
- if ! device_exists ${device}; then
- error "Device '${device}' does not exist."
- return ${EXIT_ERROR}
- fi
+ # Return an error if the device does not exist
+ device_exists ${device} || return ${EXIT_ERROR}
echo $(<${SYS_CLASS_NET}/${device}/mtu)
}
local device=${1}
local mtu=${2}
- if ! device_exists ${device}; then
- error "Device '${device}' does not exist."
- return ${EXIT_ERROR}
- fi
-
- local oldmtu=$(device_get_mtu ${device})
-
- if [ "${oldmtu}" = "${mtu}" ]; then
- # No need to set mtu.
- return ${EXIT_OK}
- fi
+ assert device_exists ${device}
- log INFO "Setting mtu of '${device}' to '${mtu}' - was ${oldmtu}."
+ log INFO "Setting MTU of ${device} to ${mtu}"
local up
if device_is_up ${device}; then
up=1
fi
- ip link set ${device} mtu ${mtu}
- local ret=$?
+ local ret=${EXIT_OK}
+ if ! cmd ip link set ${device} mtu ${mtu}; then
+ ret=${EXIT_ERROR}
- if [ "${up}" = "1" ]; then
- device_set_up ${device}
+ log ERROR "Could not set MTU ${mtu} on ${device}"
fi
- if [ "${ret}" != "0" ]; then
- error_log "Could not set mtu '${mtu}' on device '${device}'."
+ if [ "${up}" = "1" ]; then
+ device_set_up ${device}
fi
return ${ret}
done
}
+device_identify() {
+ assert [ $# -ge 1 ]
+
+ local device="${1}"
+
+ # Flash for ten seconds by default
+ local seconds="10"
+
+ # Run in background?
+ local background="false"
+
+ local arg
+ while read arg; do
+ case "${arg}" in
+ --background)
+ background="true"
+ ;;
+ --seconds=*)
+ seconds="$(cli_get_val "${arg}")"
+ ;;
+ esac
+ done <<< "$(args $@)"
+
+ assert isinteger seconds
+
+ if ! device_exists "${device}"; then
+ log ERROR "Cannot identify device ${device}: Does not exist"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! device_is_ethernet "${device}"; then
+ log DEBUG "Cannot identify device ${device}: Not an ethernet device"
+ return ${EXIT_NOT_SUPPORTED}
+ fi
+
+ log DEBUG "Identifying device ${device}"
+
+ local command="ethtool --identify ${device} ${seconds}"
+ local ret=0
+
+ if enabled background; then
+ cmd_background "${command}"
+ else
+ cmd_quiet "${command}"
+ ret=$?
+ fi
+
+ return ${ret}
+}
+
device_has_ip() {
local device=${1}
local addr=${2}
print "${s}"
}
+
+device_auto_configure_smp_affinity() {
+ assert [ $# -eq 1 ]
+
+ local device=${1}
+
+ if lock_acquire "smp-affinity"; then
+ device_set_smp_affinity "${port}" auto
+
+ lock_release "smp-affinity"
+ fi
+}
+
+device_set_smp_affinity() {
+ assert [ $# -eq 2 ]
+
+ local device=${1}
+ local mode=${2}
+
+ # mode can be auto which will automatically try to find
+ # the least busy processor, or an integer for the desired
+ # processor that should handle this device
+
+ local num_processors=$(system_get_processors)
+
+ if [ "${mode}" = "auto" ]; then
+ local processor=$(interrupt_choose_least_busy_processor)
+ else
+ assert isinteger mode
+ local processor=${mode}
+
+ if [ ${processor} -gt ${num_processors} ]; then
+ log ERROR "Processor ${processor} does not exist"
+ return ${EXIT_ERROR}
+ fi
+ fi
+
+ local interrupts=$(interrupts_for_device ${device})
+ if ! isset interrupts; then
+ log DEBUG "${device} has no interrupts. Not changing SMP affinity"
+ return ${EXIT_OK}
+ fi
+
+ # Set SMP affinity
+ local interrupt
+ for interrupt in ${interrupts}; do
+ interrupt_set_smp_affinity ${interrupt} ${processor}
+ done
+
+ # Find all queues and assign them to the next processor
+ local queue
+ for queue in $(device_get_queues ${device}); do
+ case "${queue}" in
+ # Only handle receive queues
+ rx-*)
+ for interrupt in $(interrupts_for_device_queue ${device} ${queue}); do
+ interrupt_set_smp_affinity ${interrupt} ${processor}
+ done
+
+ device_queue_set_smp_affinity ${device} ${queue} ${processor}
+ ;;
+
+ # Ignore the rest
+ *)
+ continue
+ ;;
+ esac
+
+ # Get the next available processor if in auto mode
+ [ "${mode}" = "auto" ] && processor=$(system_get_next_processor ${processor})
+ done
+
+ return ${EXIT_OK}
+}
+
+device_get_queues() {
+ assert [ $# -eq 1 ]
+
+ local device=${1}
+
+ local queue
+ for queue in ${SYS_CLASS_NET}/${device}/queues/*; do
+ basename "${queue}"
+ done
+}
+
+device_queue_set_smp_affinity() {
+ assert [ $# -eq 3 ]
+
+ local device=${1}
+ local queue=${2}
+ local processor=${3}
+
+ local path="${SYS_CLASS_NET}/${device}/queues/${queue}/rps_cpus"
+ assert [ -w "${path}" ]
+
+ log DEBUG "Setting SMP affinity of ${device} (${queue}) to processor ${processor}"
+
+ __processor_id_to_bitmap ${processor} > ${path}
+}