Background

Every produced PC board should be tested at production line to minimize board travel times. This means that you, as developer, should pack all the test fixtures and other stuff needed for testing, send it to the plant and write huge instruction about how to do all the testing. Every manual operation is the source of mistakes and errors. So, minimizing the number of manual instructions and simplifying testing procedure is must do!

First thing you want to do when you need to test ethernet without external router is just ping yourself via loopback plug, but that turns out to be quite hard to do because OS network stack can easily intercept those pings to itself and process it inside kernel, without sending bytes over the wire.

Googling this topic brought up alot of "trash" like double NAT to fool around OS network stack and most of these solutions were made for two network interfaces.

BUT, according to this small diagram I've prepared just for this case, ICMP requests which ping belongs to are processed on the network level, so we should go deeper, to the link layer, and OS allows us to do so.

OSI layers

Linkloop

Googling about link layer messaging revealed linkloop utility written to mimic behavior of HP linkloop utility. This utility has separate client and server parts which allows testing on the same machine and/or link layer testing between different machines on the net, but I just care about loopback linkloop. Hehe what a name.

First thing I've noticed about this tool is that it is built with autotools. Let me be clear, I dont hate autotools. I even like autotools somewhat, cant call it love or even cant say that autotools like me back though. Sooo.. I honestly failed to build linkloop with autotools =) But oh well client and server both consist just of couple of C files, so just

gcc common.c linkloop.c -o linkloop
gcc common.c linkloop_reply.c -o linkloop_reply

Hardware

This time the only thing we need is loopback plug.

Loopback plug

How to test with it

Unfortunately linkloop utility is quite unfinished in its present state at least in regards of testing. Why?

  • It does not have return codes suitable for parsing
  • Linkloop reply does not exit its infinite loop

Of course these things can be solved by parsing linkloop's stdout and by explicit pkill of linkloop_reply, but that was inconvenient for me, thats why I modified it a little. This version implements return codes and linkloop_reply exits when message is received. Modified version can be found on github.

As a result, my testing scenario looks like this:

iface=$( /sbin/ifconfig -a | grep eth | sed -e "s/^\(eth[0-9]\).*/\1/")
mac=$( /sbin/ifconfig -a | grep HWaddr | sed -e "s/^eth[0-9][a-zA-Z: ]* HWaddr \([0-9:]*\)/\1/")
operstate_path="/sys/class/net/${iface}/operstate"
NORMALTIMEOUT=120

linkloop_reply ${iface} &
sleep 1
/sbin/ifconfig ${iface} up
delay=0
while [ ${delay} -lt ${NORMALTIMEOUT} ]; do
    let delay=delay+1
    if [ "up" = $(cat ${operstate_path}) ]; then
        test_eth_link_ok=1
        break
    fi
    sleep 1;
done
sleep 1;
if [ ${test_eth_link_ok} -eq 1 ]; then
    linkloop -i ${iface} ${mac}
    ret=$?
    if [ ${ret} -eq 0 ]; then
        test_eth_loopback_ok=1
    fi
    echo "linkloop returned ${ret}"
    pkill linkloop_reply
    sleep 1;
fi

On my setup the loopback plug does not immediately cause link up on interface when it is plugged in, thats why /sys/class/net/${iface}/operstate is polled here. Besides dont forget that link may not go up at all, which can be diagnosed as a separate failure.