check_ethernet: don't ping via "down" links

I've noticed that we have some timing problems since:

https://chromium-review.googlesource.com/1637489

where we're holding /run/autotest_pause_ethernet_hook for upwards of 25
seconds. One reason: we're wasting a lot of time when there are
un-connected links (e.g., Chromeboxes with built-in Ethernet, but the
lab uses a USB dongle). Don't bother pinging anything if the operational
state is not "up".

Per Linux documentation:

  Indicates the interface RFC2863 operational state as a string.
  Possible values are:
  "unknown", "notpresent", "down", "lowerlayerdown", "testing",
  "dormant", "up".

BUG=none
TEST=plug in an unused USB ethernet dongle; ensure only eth1 is active;
     then watch how long check_ethernet.hook takes

Change-Id: I8c1288c36cc9b15347dc8ea86cafb2e4bf12fb9f
Reviewed-on: https://chromium-review.googlesource.com/1669972
Tested-by: Brian Norris <briannorris@chromium.org>
Commit-Ready: Brian Norris <briannorris@chromium.org>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Grant Grundler <grundler@chromium.org>
diff --git a/recover_duts/hooks/check_ethernet.hook b/recover_duts/hooks/check_ethernet.hook
index 7ad20a5..0f42e34 100755
--- a/recover_duts/hooks/check_ethernet.hook
+++ b/recover_duts/hooks/check_ethernet.hook
@@ -52,13 +52,21 @@
   done
 }
 
+# Optional arg: when non-empty, only check for operational links.
 search_devices() {
   local device_path
   local device
+  local operational="$1"
 
   for device_path in /sys/class/net/*; do
     device="$(basename "${device_path}")"
 
+    # Skip non-operational links.
+    if [ -n "${operational}" ] && \
+       [ "$(cat "${device_path}/operstate")" != "up" ]; then
+        continue
+    fi
+
     # lab interconnect is full-duplex and tells us so.
     # devices w/o link won't get listed here
     if cat "${device_path}/duplex" > /dev/null 2>&1 ; then
@@ -86,10 +94,12 @@
 }
 
 # Shows the list of Ethernet interfaces found on the system.
+# Optional arg: when non-empty, only check for operational links.
 find_ethernet_interfaces() {
   local interfaces
+  local operational="$1"
 
-  interfaces=$(search_devices)
+  interfaces=$(search_devices "${operational}")
   if [ -z "${interfaces}" ] ; then
     # didn't find any eth devices.
     # Some possible causes are:
@@ -101,19 +111,19 @@
     rescan_usb_hubs
 
     # check again
-    interfaces=$(search_devices)
+    interfaces=$(search_devices "${operational}")
   fi
   echo "$interfaces"
 }
 
 
-# Pings the given ipaddress through all ethernet devices
+# Pings the given ipaddress through all operational ethernet devices
 # $1 - IP address to ping.
 do_ping() {
   local ip_addr=$1
   local eth
 
-  for eth in $(find_ethernet_interfaces); do
+  for eth in $(find_ethernet_interfaces 1); do
     ping -q -I "${eth}" -c 9 "${ip_addr}" && return 0
   done
 
@@ -132,7 +142,7 @@
   local eth
   local neighbor_ip
 
-  for eth in $(find_ethernet_interfaces); do
+  for eth in $(find_ethernet_interfaces 1); do
     neighbor_ip=$(ip -4 neigh show dev "${eth}" |
                   awk '/REACHABLE|DELAY|STALE/ {print $1; exit}')
     [ -n "${neighbor_ip}" ] && echo "${neighbor_ip}" && return 0