X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Fnetwork.git;a=blobdiff_plain;f=src%2Ffunctions%2Ffunctions.device;h=d1f60c436572fee5c48ea825967959631efb3f3c;hp=97eb17f794bd174f8c42a69eef005ceca7b49cb4;hb=5ee61d861950b44ce011c9d9845ca1b38209ac3a;hpb=b9f27bafefdd906313c70335cfc198fe32b41189 diff --git a/src/functions/functions.device b/src/functions/functions.device index 97eb17f7..d1f60c43 100644 --- a/src/functions/functions.device +++ b/src/functions/functions.device @@ -19,47 +19,34 @@ # # ############################################################################### -function devicify() { - local device=${1} - - assert isset device - - if device_exists ${device}; then - echo "${device}" - return ${EXIT_OK} - fi - - local d - for d in $(devices_get_all); do - if [ "$(device_get_address ${d})" = "${device}" ]; then - echo "${d}" - return ${EXIT_OK} +declare -A DEVICE_LINK_SPEEDS=( + [10BaseT-Half]=0x1 + [10BaseT-Full]=0x2 + [100BaseT-Half]=0x4 + [100BaseT-Full]=0x8 + [1000BaseT-Half]=0x10 + [1000BaseT-Full]=0x20 + [10000BaseT-Full]=0x1000 +) + +device_list() { + # Add all interfaces + local device + for device in $(list_directory ${SYS_CLASS_NET}); do + if device_exists "${device}"; then + print "${device}" fi done - return ${EXIT_ERROR} -} - -function macify() { - local device=${1} - - assert isset device - - if mac_is_valid ${device}; then - echo "${device}" - return ${EXIT_OK} - fi - - if device_exists ${device}; then - device_get_address ${device} - return ${EXIT_OK} - fi + # List all PHYs + phy_list - return ${EXIT_ERROR} + # List all serial devices + serial_list } # Check if the device exists -function device_exists() { +device_exists() { local device=${1} # If device name was not found, exit. @@ -68,12 +55,16 @@ function device_exists() { # Check for a normal network device. [ -d "${SYS_CLASS_NET}/${device}" ] && return ${EXIT_OK} - # If the check above, did not find a result, + # If the check above did not find a result, + # we check for PHYs. + phy_exists "${device}" && return ${EXIT_OK} + + # If the check above did not find a result, # we check for serial devices. serial_exists ${device} } -function device_matches_pattern() { +device_matches_pattern() { local device="${1}" assert isset device @@ -86,13 +77,16 @@ function device_matches_pattern() { && return ${EXIT_TRUE} || return ${EXIT_FALSE} } -function device_delete() { +device_delete() { local device=${1} assert isset device # Nothing to do, it device does not exist. device_exists ${device} || return ${EXIT_OK} + # Shut down device before we delete it + device_set_down "${device}" + # Delete the device. cmd_quiet ip link delete ${device} local ret=$? @@ -105,7 +99,7 @@ function device_delete() { return ${ret} } -function device_has_flag() { +device_has_flag() { local device=${1} local flag=${2} @@ -119,7 +113,7 @@ function device_has_flag() { } # Check if the device is up -function device_is_up() { +device_is_up() { local device=${1} device_exists ${device} || return ${EXIT_ERROR} @@ -127,15 +121,12 @@ function device_is_up() { device_has_flag ${device} 0x1 } -function device_ifindex_to_name() { +device_ifindex_to_name() { local idx=${1} assert isset idx local device device_idx - for device in ${SYS_CLASS_NET}/*; do - device=$(basename ${device}) - device_exists ${device} || continue - + for device in $(list_directory "${SYS_CLASS_NET}"); do device_idx=$(device_get_ifindex ${device}) if [ "${device_idx}" = "${idx}" ]; then @@ -147,7 +138,7 @@ function device_ifindex_to_name() { return ${EXIT_ERROR} } -function device_get_ifindex() { +device_get_ifindex() { local device=${1} assert isset device @@ -159,54 +150,36 @@ function device_get_ifindex() { print "$(<${path})" } -# Check if the device is a batman-adv bridge -function device_is_batman_adv() { - [ -d "${SYS_CLASS_NET}/${1}/mesh" ] -} - -# Check if the device is a batman-adv slave port -function device_is_batman_adv_slave() { +device_get_driver() { local device="${1}" + assert isset device - if [ -d "${SYS_CLASS_NET}/${device}/batman_adv" ]; then - local status="$(<${SYS_CLASS_NET}/${device}/batman_adv/iface_status)" - - case "${status}" in - "active") - return ${EXIT_TRUE} - ;; - *) - return ${EXIT_FALSE} - ;; - esac - fi - - return ${EXIT_FALSE} + get_driver_from_path "${SYS_CLASS_NET}/${device}/device/driver/module" } # Check if the device is a bonding device -function device_is_bonding() { +device_is_bonding() { [ -d "/sys/class/net/${1}/bonding" ] } # Check if the device bonded in a bonding device -function device_is_bonded() { +device_is_bonded() { local device=${1} [ -d "${SYS_CLASS_NET}/${device}/bonding_slave" ] } # Check if the device is a bridge -function device_is_bridge() { +device_is_bridge() { [ -d "/sys/class/net/${1}/bridge" ] } -function device_is_bridge_attached() { +device_is_bridge_attached() { local device=${1} [ -d "${SYS_CLASS_NET}/${device}/brport" ] } -function device_is_wireless_monitor() { +device_is_wireless_monitor() { local device="${1}" assert isset device @@ -214,7 +187,7 @@ function device_is_wireless_monitor() { device_matches_pattern "${device}" "${PORT_PATTERN_WIRELESS_MONITOR}" } -function device_is_wireless_adhoc() { +device_is_wireless_adhoc() { local device="${1}" assert isset device @@ -222,7 +195,7 @@ function device_is_wireless_adhoc() { device_matches_pattern "${device}" "${PORT_PATTERN_WIRELESS_ADHOC}" } -function device_get_bridge() { +device_get_bridge() { local device=${1} assert isset device @@ -239,7 +212,7 @@ function device_get_bridge() { } # Check if the device is a vlan device -function device_is_vlan() { +device_is_vlan() { local device=${1} assert isset device @@ -247,7 +220,7 @@ function device_is_vlan() { } # Check if the device has vlan devices -function device_has_vlans() { +device_has_vlans() { local device=${1} assert isset device @@ -259,7 +232,7 @@ function device_has_vlans() { [ -n "${vlans}" ] && return ${EXIT_OK} || return ${EXIT_ERROR} } -function device_get_vlans() { +device_get_vlans() { local device=${1} assert isset device @@ -275,37 +248,77 @@ function device_get_vlans() { done < ${PROC_NET_VLAN_CONFIG} } -# Check if the device is a ppp device -function device_is_ppp() { - local device=${1} +__device_type_matches() { + local device="${1}" + local type="${2}" + + local _type="$(__device_get_file "${device}" "type")" + + if [ "${type}" = "${_type}" ]; then + return ${EXIT_TRUE} + fi - local type=$(__device_get_file ${device} type) + return ${EXIT_FALSE} +} + +# Check if the device is a ppp device +device_is_ppp() { + local device="${1}" + assert isset device - [ "${type}" = "512" ] && return ${EXIT_OK} || return ${EXIT_ERROR} + __device_type_matches "${device}" 512 } # Check if the device is a pointopoint device. -function device_is_ptp() { +device_is_ptp() { local device=${1} device_has_flag ${device} 0x10 } # Check if the device is a loopback device -function device_is_loopback() { +device_is_loopback() { local device=${1} [ "${device}" = "lo" ] } +# Check if the device is a dummy device +# This is the worst possible check, but all I could come up with +device_is_dummy() { + local device="${1}" + + [[ ${device} =~ ^dummy[0-9]+$ ]] +} + +device_is_ipsec() { + local device="${1}" + + [[ ${device} =~ ^ipsec\- ]] +} + # Check if the device is a wireless device -function device_is_wireless() { +device_is_wireless() { local device=${1} [ -d "${SYS_CLASS_NET}/${device}/phy80211" ] } -function device_get_phy() { +device_is_vti() { + local device="${1}" + assert isset device + + __device_type_matches "${device}" 768 +} + +device_is_vti6() { + local device="${1}" + assert isset device + + __device_type_matches "${device}" 769 +} + +device_get_phy() { local device="${1}" if device_is_wireless "${device}"; then @@ -316,14 +329,28 @@ function device_get_phy() { return ${EXIT_ERROR} } -function device_is_serial() { - serial_exists $@ +device_is_phy() { + phy_exists "$@" +} + +device_is_serial() { + serial_exists "$@" +} + +# Returns true if a device is a tun device +device_is_tun() { + local device="${1}" + + [ -e "${SYS_CLASS_NET}/${device}/tun_flags" ] } # Check if the device is a physical network interface -function device_is_ethernet() { +device_is_ethernet() { local device=${1} + device_is_ethernet_compatible "${device}" || \ + return ${EXIT_ERROR} + device_is_loopback ${device} && \ return ${EXIT_ERROR} @@ -339,14 +366,17 @@ function device_is_ethernet() { device_is_vlan ${device} && \ return ${EXIT_ERROR} - [ "$(__device_get_file ${device} type)" != "1" ] && \ + device_is_dummy ${device} && \ + return ${EXIT_ERROR} + + device_is_tun ${device} && \ return ${EXIT_ERROR} return ${EXIT_OK} } # Get the device type -function device_get_type() { +device_get_type() { local device=${1} # If the device does not exist (happens on udev remove events), @@ -366,9 +396,6 @@ function device_get_type() { elif device_is_ppp ${device}; then echo "ppp" - elif device_is_batman_adv ${device}; then - echo "batman-adv" - elif device_is_loopback ${device}; then echo "loopback" @@ -378,18 +405,56 @@ function device_get_type() { elif device_is_wireless ${device}; then echo "wireless" + elif device_is_dummy ${device}; then + echo "dummy" + + elif device_is_tun ${device}; then + echo "tun" + elif device_is_ethernet ${device}; then echo "ethernet" elif device_is_serial ${device}; then echo "serial" + elif device_is_phy ${device}; then + echo "phy" + + else + echo "$(device_tunnel_get_type "${device}")" + fi +} + +# This function just checks the types a ip-tunnel device usually have +# so when we know that the device is an ip-tunnel device we save time +device_tunnel_get_type() { + local device=${1} + + # If the device does not exist (happens on udev remove events), + # we do not bother to run all checks. + if ! device_exists "${device}"; then + echo "unknown" + + elif device_is_vti ${device}; then + echo "vti" + + elif device_is_vti6 ${device}; then + echo "vti6" + else echo "unknown" fi } -function device_get_status() { +device_is_ethernet_compatible() { + local device="${1}" + + # /sys/class/net/*/type must equal 1 for ethernet compatible devices + local type="$(__device_get_file "${device}" "type")" + [[ "${type}" = "1" ]] +} + +device_get_status() { local device=${1} assert isset device @@ -406,13 +471,13 @@ function device_get_status() { echo "${status}" } -function device_get_address() { +device_get_address() { local device=${1} cat ${SYS_CLASS_NET}/${device}/address 2>/dev/null } -function device_set_address() { +device_set_address() { assert [ $# -eq 2 ] local device="${1}" @@ -451,29 +516,20 @@ function device_set_address() { return ${ret} } -function device_get() { +device_get() { local device - local devices - - for device in ${SYS_CLASS_NET}/*; do - device=$(basename ${device}) - + for device in $(list_directory "${SYS_CLASS_NET}"); do # bonding_masters is no device [ "${device}" = "bonding_masters" ] && continue - devices="${devices} ${device}" + echo "${device}" done - echo ${devices} return ${EXIT_OK} } -function devices_get_all() { - device_get -} - # Check if a device has a cable plugged in -function device_has_carrier() { +device_has_carrier() { local device=${1} assert isset device @@ -481,13 +537,13 @@ function device_has_carrier() { [ "${carrier}" = "1" ] } -function device_is_promisc() { +device_is_promisc() { local device=${1} device_has_flag ${device} 0x200 } -function device_set_promisc() { +device_set_promisc() { local device=${1} local state=${2} @@ -499,12 +555,12 @@ function device_set_promisc() { } # Check if the device is free -function device_is_free() { - ! device_is_used $@ +device_is_free() { + ! device_is_used "$@" } # Check if the device is used -function device_is_used() { +device_is_used() { local device=${1} device_has_vlans ${device} && \ @@ -517,18 +573,8 @@ function device_is_used() { return ${EXIT_ERROR} } -function device_hash() { - local device=${1} - - # Get mac address of device and remove all colons (:) - # that will result in a hash. - device=$(macify ${device}) - - echo "${device//:/}" -} - # Give the device a new name -function device_set_name() { +device_set_name() { local source=$1 local destination=${2} @@ -550,24 +596,58 @@ function device_set_name() { fi } +device_set_master() { + local device="${1}" + assert isset device + + local master="${2}" + assert isset master + + if ! cmd ip link set "${device}" master "${master}"; then + log ERROR "Could not set master ${master} for device ${device}" + return ${EXIT_ERROR} + fi + + return ${EXIT_OK} +} + +device_remove_master() { + local device="${1}" + assert isset device + + if ! cmd ip link set "${device}" nomaster; then + log ERROR "Could not remove master for device ${device}" + return ${EXIT_ERROR} + fi + + return ${EXIT_OK} +} + # Set device up -function device_set_up() { - local device=${1} +device_set_up() { + 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 ${device} + fi - ip link set ${device} up + return ${EXIT_OK} } -function device_set_parent_up() { +device_set_parent_up() { local device=${1} local parent @@ -586,16 +666,16 @@ function device_set_parent_up() { } # Set device down -function device_set_down() { - local device=${1} - assert isset device +device_set_down() { + 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 @@ -604,7 +684,7 @@ function device_set_down() { return ${ret} } -function device_set_parent_down() { +device_set_parent_down() { local device=${1} local parent @@ -623,35 +703,31 @@ function device_set_parent_down() { return ${EXIT_OK} } -function device_get_mtu() { +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) } # Set mtu to a device -function device_set_mtu() { +device_set_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}) + assert device_exists ${device} - if [ "${oldmtu}" = "${mtu}" ]; then - # No need to set mtu. - return ${EXIT_OK} + # Handle bridges differently + if device_is_bridge ${device}; then + local port + for port in $(bridge_get_members ${device}); do + device_set_mtu ${port} ${mtu} + done fi - 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 @@ -659,21 +735,21 @@ function device_set_mtu() { 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} } -function device_adjust_mtu() { +device_adjust_mtu() { assert [ $# -eq 2 ] local device="${1}" @@ -683,7 +759,7 @@ function device_adjust_mtu() { device_set_mtu "${device}" "${mtu}" } -function device_discover() { +device_discover() { local device=${1} log INFO "Running discovery process on device '${device}'." @@ -694,7 +770,57 @@ function device_discover() { done } -function device_has_ip() { +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} @@ -705,14 +831,14 @@ function device_has_ip() { local protocol=$(ip_detect_protocol ${addr}) case "${protocol}" in ipv6) - addr=$(ipv6_implode ${addr}) + addr=$(ipv6_format "${addr}") ;; esac - listmatch ${addr} $(device_get_addresses ${device}) + list_match ${addr} $(device_get_addresses ${device}) } -function device_get_addresses() { +device_get_addresses() { local device=${1} assert device_exists ${device} @@ -726,84 +852,124 @@ function device_get_addresses() { done } -function __device_get_file() { +__device_get_file() { local device=${1} local file=${2} - assert isset device - assert isset file - - local path="${SYS_CLASS_NET}/${device}/${file}" - [ -r "${path}" ] || return ${EXIT_ERROR} - - echo "$(<${path})" + fread "${SYS_CLASS_NET}/${device}/${file}" } -function __device_set_file() { +__device_set_file() { assert [ $# -eq 3 ] local device="${1}" local file="${2}" local value="${3}" - local path="${SYS_CLASS_NET}/${device}/${file}" - if [ ! -w "${path}" ]; then - log DEBUG "Cannot write to file '${file}' (${value})" - return ${EXIT_ERROR} - fi - - echo "${value}" > "${path}" + fappend "${SYS_CLASS_NET}/${device}/${file}" "${value}" } -function device_get_rx_bytes() { +device_get_rx_bytes() { local device=${1} __device_get_file ${device} statistics/rx_bytes } -function device_get_tx_bytes() { +device_get_tx_bytes() { local device=${1} __device_get_file ${device} statistics/tx_bytes } -function device_get_rx_packets() { +device_get_rx_packets() { local device=${1} __device_get_file ${device} statistics/rx_packets } -function device_get_tx_packets() { +device_get_tx_packets() { local device=${1} __device_get_file ${device} statistics/tx_packets } -function device_get_rx_errors() { +device_get_rx_errors() { local device=${1} __device_get_file ${device} statistics/rx_errors } -function device_get_tx_errors() { +device_get_tx_errors() { local device=${1} __device_get_file ${device} statistics/tx_errors } -function device_get_speed() { +device_advertise_link_speeds() { + local device="${1}" + shift + + assert isset device + + # Advertised modes in hex + local advertise=0 + + local mode + for mode in $@; do + local m="${DEVICE_LINK_SPEEDS[${mode}]}" + if isset m; then + advertise="$(( advertise | m ))" + fi + done + + # If nothing was selected, we reset and enable everything + if [ ${advertise} -eq 0 ]; then + advertise=0xffffff + fi + + # Enable auto-negotiation + cmd_quiet ethtool --change "${device}" autoneg on + + # Set advertised link speeds + if ! cmd_quiet ethtool --change "${device}" advertise "0x$(hex "${advertise}")"; then + log ERROR "Could not set link modes of ${device}: $@" + return ${EXIT_ERROR} + fi + + log DEBUG "Set device link modes of ${device} to $@" + return ${EXIT_ERROR} +} + +device_get_speed() { local device=${1} - __device_get_file ${device} speed + local speed=$(__device_get_file ${device} speed) + + # Exit for no output (i.e. no link detected) + isset speed || return ${EXIT_ERROR} + + # Don't return anything for negative values + [ ${speed} -lt 0 ] && return ${EXIT_ERROR} + + print "${speed}" } -function device_get_duplex() { +device_get_duplex() { local device=${1} - __device_get_file ${device} duplex + local duplex=$(__device_get_file ${device} duplex) + + case "${duplex}" in + unknown) + return ${EXIT_ERROR} + ;; + *) + print "${duplex}" + ;; + esac } -function device_get_link_string() { +device_get_link_string() { local device="${1}" assert isset device @@ -821,3 +987,204 @@ function device_get_link_string() { print "${s}" } + +device_auto_configure_smp_affinity() { + assert [ $# -eq 1 ] + + local device=${1} + + if lock_acquire "smp-affinity" 60; then + device_set_smp_affinity ${device} 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} + + list_directory "${SYS_CLASS_NET}/${device}/queues" +} + +device_supports_multiqueue() { + local device=${1} + + local num_queues=$(device_num_queues ${device}) + + if isset num_queues && [ ${num_queues} -gt 2 ]; then + return ${EXIT_TRUE} + fi + + return ${EXIT_FALSE} +} + +device_num_queues() { + local device=${1} + local type=${2} + + isset type && assert isoneof type rx tx + + local i=0 + + local q + for q in $(device_get_queues ${device}); do + case "${type},${q}" in + rx,rx-*) + (( i++ )) + ;; + tx,tx-*) + (( i++ )) + ;; + *,*) + (( i++ )) + ;; + esac + done + + print ${i} +} + +device_queue_get_smp_affinity() { + assert [ $# -eq 2 ] + + local device=${1} + local queue=${2} + + local path="${SYS_CLASS_NET}/${device}/queues/${queue}" + + case "${queue}" in + rx-*) + path="${path}/rps_cpus" + ;; + tx-*) + path="${path}/xps_cpus" + ;; + esac + assert [ -r "${path}" ] + + __bitmap_to_processor_ids $(<${path}) +} + +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} +} + +# Tries to find a device which has the given IP address assigned +device_get_by_assigned_ip_address() { + local ip=${1} + + assert isset ip + + local device + + # Read the first line of ip addr show to + read -r device <<< $(ip addr show to "${ip}") + + # If we did not found a device we return with ${EXIT_ERROR} + if ! isset device; then + return ${EXIT_ERROR} + fi + + # We get something like: + # 3: upl0: mtu 1500 qdisc mq state UP group default qlen 1000 + # and we want upl0 so we take the second word and removing the : + device=(${device}) + device=${device[1]} + device=${device%:} + + print "${device}" + return ${EXIT_OK} +} + +device_get_by_mac_address() { + local mac=${1} + + assert isset mac + + local device + + for device in $(device_list); do + if [ "${mac}" = "$(device_get_address ${device})" ]; then + print "${device}" + return ${EXIT_OK} + fi + done + + # We could not found a port to the given mac address so we return exit error + return ${EXIT_ERROR} +}