1 (edited by eigma 2013-12-26 04:01:43)

Topic: How does hotplug work for network interfaces?

I'm trying to wrap my mind around the full sequence of events from an interface coming up (or its address changing) to the scripts in /etc/hotplug.d/iface being called. I'm specifically interested in this for ddns purposes (ddns-scripts packages drops a 25-ddns script there), but the discussion should apply more generally.

I start in the kernel, where subsystems can inject a uevent using kobject_uevent:

That takes an enum for the action, which is stringified according to this LUT for inclusion in the netlink message as "ACTION=":
The possible values are: add, remove, change, move, online, offline.

I looked around linux/net/ for call sites of kobject_uevent and it seems like net only delivers add/remove for devices as a whole, plus change for a few protocol/driver specific cases like rfkill. No interface address change events? Anyway, let's continue..

From here procd appears to create a netlink socket and pump events out of it:
http://nbd.name/gitweb.cgi?p=luci2/proc … =HEAD#l451

There doesn't seem to be much event-specific handling in C code, but there is a mini domain-specific language (why a new language instead of bash or lua?) expressed in JSON that takes care of certain subsystems specially:

netifd *also* creates a netlink socket and pumps events out of it:
http://nbd.name/gitweb.cgi?p=luci2/neti … =HEAD#l141

netifd seems to handle "add" and "remove" events only, using them to update internal state about device presence and to rebroadcast state changes to internal subscribers. I see calls to device_claim in alias.c, bridge.c, vlan.c, a few others. Do these events somehow end up on ubus? Are there any bash scripts (ala /etc/hotplug.d) executed as a result of these events? examples/hotplug-cmd seems to be a hotplug script, when does this come into play?

Going back to procd, the openwrt hotplug.json, for "net" events, runs /sbin/hotplug-call %SUBSYSTEM%. This runs the scripts in /etc/hotplug.d/net with environment from the uevent:

hotplug.json has no configuration for SUBSYSTEM=iface. Are these events swallowed? What about the "ifup" and "ifdown" values for ACTION? (these are documented on the wiki: http://wiki.openwrt.org/doc/techref/hotplug and used by the scripts in /etc/hotplug.d/iface) I'm starting to think SUBSYSTEM=iface may not actually exist..

Does uevent deliver events only for device add/remove, or also when an interface alias is created? What about when the addresses of an interface change? I tried answering some of these questions by running 'strace -f -p 1' (stracing procd) and bringing up an alias of lo (ifconfig lo:1 netmask but it didn't seem to get any events. I also tried stracing netifd, again with no visible effects. I can't easily play with the other interface on this router because it's in active use.

The reason I'm doing this is I suspect ddns-scripts is not being triggered when my WAN interface gets an IP. It has the following script in /etc/hotplug.d/iface/25-ddns:

. /usr/lib/ddns/dynamic_dns_functions.sh

if [ "$ACTION" = "ifup" ]; then
    start_daemon_for_all_ddns_sections "$INTERFACE"

In my case the WAN proto is DHCP - I want an event when WAN gets an IP (*after* the underlying network device has come up). What is the best hook to trigger for this? I have another router that uses PPP on wan so I'm looking for a generic solution.


2 (edited by eigma 2013-12-27 08:15:02)

Re: How does hotplug work for network interfaces?

While I was away my router did a renew of its wan lease:

Thu Dec 26 23:24:20 2013 daemon.notice netifd: wan (833): Sending renew...
Thu Dec 26 23:24:20 2013 daemon.notice netifd: wan (833): Lease of obtained, lease time 3600
Thu Dec 26 23:24:20 2013 user.notice firewall: Reloading firewall due to ifup of wan ()

That last log from firewall is from /etc/hotplug.d/iface/20-firewall so it looks like netifd does call those scripts.

[strike]It also looks like ACTION=ifup gets emitted for lease renews as well (when the interface already has an address).[/strike] EDIT: ACTION=ifupdate on dhcp renews

Re: How does hotplug work for network interfaces?

Aha, from netifd interface-event.c:

    char *eventnames[] = {"ifdown", "ifup", "ifupdate"};
    setenv("ACTION", eventnames[event], 1);
    setenv("INTERFACE", ifname, 1);
    if (device)
        setenv("DEVICE", device, 1);
    argv[0] = hotplug_cmd_path;
    argv[1] = "iface";
    argv[2] = NULL;
    execvp(argv[0], argv);

netifd's cycle appears to be:
- Start some proto-specific mechanism for acquiring interface configuration. For DHCP this is driven by proto-shell.c, which spawns /lib/netifd/proto/dhcp.sh, which is a thin wrapper around udhcpc. udhcpc is long-lived and set up to call back into /lib/netifd/dhcp.script for dhcp events:
  833 root      1488 S    udhcpc -p /var/run/udhcpc-eth1.pid -s /lib/netifd/dhcp.script -f -t 0 -i eth1 -C

- dhcp.script packages variables from udhcpc into json and end up doing 'ubus call network.interface notify_proto <json>'. This in turn is handled by netifd in proto-shell.c, in proto_shell_notify. Action is 0, which leads into proto_shell_update_link.

- proto_shell_update_link delivers an event to the interface through state->proto.proto_event (interface_proto_cb), which calls interface_event, which leads to the snippet above, calling into /sbin/hotplug-call with ACTION=ifupdate.

Re: How does hotplug work for network interfaces?

Hi eigma -

thanks for the analysis -

i do run in the same circles for a while now.

Still now clue why not getting event-actions on wan up or other interfaces coming up/down

Do you have some more insight to help me out ?

Wondering abt these json "script" containers also -seems quite wierd to me - is there any infor for the concept behind this ?


"use  *search* or give me your  I*  so i can show you"

        mesh applications with batman-adv