From 0599a9279170a2bec64bc432668447d4ae7a428e Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 21 Jun 2023 16:58:55 +0200 Subject: network: add support for LED triggers Some boards come with interfaces having no LED, and instead they rely on software-controllable LEDs. While we've implemented the alix-leds project in the past to deal with this, modern kernels support LED triggers for network interface link events. This patch makes use of this mechanism. It provides a new "led" option in the network section, which designates the LED name. Once up, the interface will be attached there so that the link status is reflected on the LED. There's one caveat however: turning the interface down will automatically unregister it, which means that bridges and bonds turn this off. For this reason, there's an explicit search there when attaching a slave for a possible "led" in the interface being attached, to turn it on again. --- sbin/init.d/network | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/sbin/init.d/network b/sbin/init.d/network index 184aaf0..a935050 100755 --- a/sbin/init.d/network +++ b/sbin/init.d/network @@ -17,6 +17,7 @@ # ip6 [addr ] [] : set IPv6 address" # ip6 [neigh {|proxy}] [] : set IPv6 neighbor (IPv6 equiv to ARP)" # ip6 [route <-|gw6>] [] : set IPv6 routes" +# led []: show link status on this led (optionally with event type)" # lladdr : set interface MAC address" # load|unload : commands to be executed when interface is brought up/down" # media auto|{full|fdx|100full|100fdx}|{half|hdx|100half|100hdx} (deprecated, use speed & duplex)" @@ -88,6 +89,7 @@ option sysctl multiple_option option sysctl6 multiple_option option sysset multiple_option option modprobe multiple_option +option led option_led option lladdr standard_option option mtu standard_option option arp boolean_option 1 @@ -128,6 +130,7 @@ function do_help { echo " - ip6 [neigh {|proxy}] [] : set IPv6 neighbor (IPv6 equiv to ARP)" echo " - ip6 [route <-|gw6>] [] : set IPv6 routes" echo " - ip6 [rule] []* : add IPv6 policy rule" + echo " - led []: use this LED for link status (optionally with event type)" echo " - lladdr : set interface MAC address" echo " - load|unload : commands to be executed when interface is brought up/down" echo " - media auto|{full|fdx|100full|100fdx}|{half|hdx|100half|100hdx} (deprecated, use speed & duplex)" @@ -224,6 +227,28 @@ function set_fctl { esac } +# Enables a led trigger for a network interface if available. +# Takes the interface name on $1, the LED name in $2, and optional event in $3 +# (defaults to "link"). Silently ignores non-existing interfaces, missing leds +# and missing arguments. +function set_leds { + local intf="$1" + local led="$2" + local evt="${3:-link}" + local phy + + [ -n "$intf" -a -n "$led" ] || return 0 + [ -e "/sys/class/leds/$led/trigger" ] || return 0 + [ -e "/sys/class/net/$intf/phydev" ] || return 0 + + # return the phy in form name-addr + phy=$(readlink -s "/sys/class/net/$intf/phydev" 2>/dev/null) + [ -n "$phy" ] || return 0 + phy="${phy##*/}" + ( echo "$phy:$evt" > "/sys/class/leds/$led/trigger" ) 2>/dev/null + return 0 +} + function fct_begin_section { addr_list=( ) addr6_list=( ) @@ -366,6 +391,13 @@ function option_ip6 { esac } +# parse "led []" +function option_led { + shift + opt_led="$1" + opt_led_evt="$2" +} + # used with config.rc param: cpumask # first arg is the interface to bind. second is mask (considered in decimal by # default but hex supported with "0x" prefix). @@ -571,6 +603,7 @@ function do_start { $0 start $arg ) >/dev/null 2>&1; then echo " ==> FAILED! need to start iface $arg before $instname" else + ( set -- $(config get "network.$arg" led); set_leds "$arg" "$2" "$3" ) 2>/dev/null if ! ip link set dev $arg master $instname; then echo " ==> Failed to add slave $arg to bridge $instname" fi @@ -725,6 +758,9 @@ function do_start { return 1 elif [ "$instname" = "lo" ] ; then ip addr del dev $instname 127.0.0.1/8 >/dev/null 2>&1 + else + # regular interface turned up. If a LED is specified, try to activate it + set_leds "$instname" "$opt_led" "$opt_led_evt" fi if [ -n "$cpumask" ] ; then @@ -766,6 +802,9 @@ function do_start { ifenslave $instname $arg >/dev/null 2>&1 ip addr flush dev $arg >/dev/null 2>&1 fi + # the enslaving turns the slave interface up again, we may need to + # set the LED indicator again. + ( set -- $(config get "network.$arg" led); set_leds "$arg" "$2" "$3" ) 2>/dev/null done if [ -e "/sys/class/net/$instname/bonding" ] ; then -- 2.35.3