This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to run a program when Ethernet cable is connected



AM335x running Arago from TI SDK 7.0 (NFS).

Any time I connect or disconnect from an Ethernet interface, I get an update in the terminal indicating that the link was connected or disconnected. What I'd like to know is how that message is getting posted. More specifically, I want to hook into the mechanism that is posting that message so I can run my own script any time an Ethernet connection is connected or disconnected (specifically only on eth0). However I'm not finding a way to do this.

Note, I have discovered that I can use ethtool to determine the interface state. And I also found the interface in /sys/class/net/eth0 that will let me query the driver for various status info. But I don't want to poll for interface status. I want to do one of the following:

  • Run a script/program when a specific network interface goes up or down and preferably only on a specific interface (eth0). 
  • Register to receive a signal that a network interface (preferably eth0) has changed connection state. 
  • Register a callback function pointer and have the OS notify my program of change of state

The simplest for my purposes is to simply have a shell script run when the Ethernet link goes up or down where arguments to the script indicate the state. However even if arguments are not passed in, I can query for the state via /sys/class/net/eth0/operstate to determine the current state. I'd just prefer an event-based execution/notification rather than a polling method.


Doing research on google, it seems using the netlink (libnl) library is how I would write a program to do this, But I'm not finding any examples on the Internet that describes doing what I'm wanting. So if anybody has suggestions, that would help out a lot.

  • I moved our post to the Sitara processors forum so that it will get visibility by the experts.

    Patrick
  • Hi Christopher,

    I'm not a SW expert, but the connect/disconnect events are detected via the MDIO interface from the PHY, so the MDIO driver is what you should look into, I think.

  • Currently when I connect into the target with an ethernet cable, I get this to appear on the terminal:

    [   47.296657] libphy: 4a101000.mdio:00 - Link is Up - 100/Full

    And then when I disconnect, I get:

    [  211.296632] libphy: 4a101000.mdio:00 - Link is Down

     

    So I know that libphy and mdio are in the mix. But I don't know how to harness them. Obviously somewhere there's a script or something that's posting this text to the terminal. I'm trying to figure out how to get whatever is posting this message to also do one of the bullet-points mentioned above when the connect/disconnect event occurs.

     

    Looking on the Internet for info on libphy and mdio isn't really producing meaningful results so far. But I have to believe there are people that have dealt with them that can give me some insight on what capabilities exist related to what I'm trying to do and how they are leveraged.

     

    In further research, it seems the netplugd would do what I need. Its original purpose seems more related to automating the call to ifup and ifdown when a cable is connected or removed. However since Arago seems to already be detecting these conditions, I don't see a need having those called. Regardless, netplugd still seemed like a technology worth looking into closer since it specifically listens for network interface up/down events and executes a user-defined script when these events occur.

     

    I downloaded source for it, got it compiled for ARM, and "installed" it in my target file system. But when launched, it isn't working quite right and I don't think it's netplugd's fault.

     

    Before I get to what it's doing, I'll explain the setup.

    The default config file netplugd is looking for is /etc/netplug/netplugd.conf so I created it and configured it for eth1. The content of the config file is literally eth1 on the 1st line and that's it. 

     

    The default script netplugd is calling is /etc/netplug.d/netplug. The script as it was downloaded with source was calling ifup and ifdown. It also has to probe the network interfaces to setup for receiving signals...the very thing I was trying to figure out how to do when I started this thread. The line in the config file doing this was pointed at /sbin/ip, but it appears ip is located in the /bin directory for Arago, so I modified the script appropriately. My rewrite looks like this now:

    #!/bin/sh
    PATH=/usr/bin:/bin:/usr/sbin:/sbin
    export PATH

    dev="$1"
    action="$2"

    case "$action" in
    in)
        if [ "$dev" == "eth1" ]; then
        echo "netplug: Running test-script.sh"
        sh /home/root/test-script.sh
        fi
        exit 1
        ;;
    out)
        if [ "$dev" == "eth1" ]; then
        echo "netplug: Running test-script.sh"
        sh /home/root/test-script.sh
        fi
        exit 1
        ;;
    probe)
        exec /bin/ip link set $dev up >/dev/null 2>&1
        exit 1    
        ;;
    *)
        echo "netplug: I have been called with a funny action of '%s'!" 1>&2
        exit 1
        ;;
    esac

    As you can see from the script, netplugd calls this script with 2 arguments, the dev and action argument. The dev argument is the interface and the action is in, out, or probe. My script is being called anytime the interface is detected to go in (i.e. up) or out (i.e. down). The contents of my test-script.sh just echos to let me know it ran.

     

    Now for the problem. The ethernet driver's signals don't seem to be working as I believe they should OR as netplugd expects. Here's what I get starting with eth1 unplugged and then plugging in and out a few times.

    root@am335x-evm:~# netplugd -F
    /etc/netplug.d/netplug eth1 probe -> pid 1552
    netplug: dev=eth1 action=probe

    At this point, I connect a cable to eth1.
    [11682.585503] libphy: 4a101000.mdio:01 - Link is Up - 10/Half
    eth1: state DOWN flags 0x00001003 UP,BROADCAST,MULTICAST -> 0x00011043 UP,BROADCAST,RUNNING,MULTICAST,10000
    /etc/netplug.d/netplug eth1 in -> pid 1553
    netplug: dev=eth1 action=in
    netplug: Running test-script.sh
    ============================
    Test Script executed.
    ============================
    eth1: state INNING pid 1553 exited status 256

    The interaction in the above is odd. I get the normal notification that the Link is up (blue).

    Then netplugd posts a message indicating state is DOWN (purple).That's disconcerting. But it hasn't actually caused a problem yet.

    When it executes the netplug script, it properly calls the script with the in action. Echos from the script that I added (green) echo the dev and action args it was called with.

    My script runs.

    Then you see eth1 go into the INNING state, whatever that is. I suspect that's supposed to be INITING or the pre-up state.

    But here's where the problem occurs:

    [11694.585527] libphy: 4a101000.mdio:01 - Link is Down
    eth1: state INSANE flags 0x00011043 UP,BROADCAST,RUNNING,MULTICAST,10000 -> 0x00001003 UP,BROADCAST,MULTICAST
    [11710.585554] libphy: 4a101000.mdio:01 - Link is Up - 10/Half
    eth1: state INSANE flags 0x00001003 UP,BROADCAST,MULTICAST -> 0x00011043 UP,BROADCAST,RUNNING,MULTICAST,10000
    [11718.585475] libphy: 4a101000.mdio:01 - Link is Down
    eth1: state INSANE flags 0x00011043 UP,BROADCAST,RUNNING,MULTICAST,10000 -> 0x00001003 UP,BROADCAST,MULTICAST
    [11724.585511] libphy: 4a101000.mdio:01 - Link is Up - 10/Half
    eth1: state INSANE flags 0x00001003 UP,BROADCAST,MULTICAST -> 0x00011043 UP,BROADCAST,RUNNING,MULTICAST,10000

    As you can see in blue, the normal libphy/mdio stuff is properly recognizing the link up and down conditions. However the spew from netplugd is indicating the signals it received from the eth1 driver are INSANE? Without looking at the netplugd code, my guess is netplugd is posting up the flags it received from the eth1 driver and as you can see the hex value is flipping between 0x00011043 and 0x00001003. The flip is consistent. So is there a chance that the eth driver isn't managing the flags correctly?

    But more importantly, the script is no longer being run. FAIL.

     

    So is this a fault of the Arago etherent driver? Has there been any significant update to the Arago ethernet driver code that would explain this? Since this is happening on our proto board, there's a chance this is something we've done. So my next step is to deploy netplugd on a BBB and see if it misbehaves the same way.

     

    In the meantime, does anybody have any thoughts?

     

    It does make me wonder if I can forego netplugd and simply "probe" /bin/ip in the same way the script does and do what I'm trying to do without netplugd? Could that even be done purely from a script or will this require C-code to receive these signals? I guess to know that, I'll have to go swimming in the netplugd source.

     

     

     

     

  • I verified that netplugd with this setup operates exactly the same with the exact same results on a BeagleBone Black (BBB). I had to modify the scripts and config file for eth0 for the BBB. But the same exact results as detailed above.
  • Looking further into this, I have some findings.

    The call to /bin/ip seems to simply be a call to bring up the interface in case it is down. It doesn't appear to setup any signal reporting or anything like that as I'd assumed earlier.

    Next, I don't think netplugd actually registers itself as a signal receiver. What I did was went into the netplugd source code and modified the INSANE case (as in switch/case) in code to do the same thing the UP and DOWN case did. This was a horribly crude modification of the code, but what happened is I got repeated calls to the script as though netplugd was polling the interface at roughly 50-100ms intervals. I didn't look into the code further, but there is a relatively complex state machine involved. So I suspect that netplugd is literally polling the interface and then manages the calling of a script when a transition from state occurs to make it appear from the user's perspective that they have event-level script execution, not a polling system. So due to my crude modification of the code, I had the state machine in a bad state that continually called my script at every poll interval. But based on this finding, I abandoned my efforts to use netplugd and just wrote my own C-based app to poll the interface at 1 second intervals and call my script with the current detected state. That seems to work just fine.

    I'd still like to find a more efficient way to do this. But this is a decent work around in the meantime.