diff mbox

package/skeleton: add a startup script to wait for slow network interfaces

Message ID 1443879105-3036-1-git-send-email-yann.morin.1998@free.fr
State Accepted
Commit 49964858f45d2243c513e6d362e992ad89ec7a45
Headers show

Commit Message

Yann E. MORIN Oct. 3, 2015, 1:31 p.m. UTC
On some machines, the network interface is slow to appear. For example,
on the Raspberry Pi, the network interface eth0 is an ethernet-over-USB,
and our standard boot process is too fast, so our network startup script
is called before the USB bus is compeltely enumerated, thus it can't
configure eth0.

If Buildroot is configured to do a DHCP on an interface, install a
startup script, just before S40network, that waits for that interface.

Since Buildroot can only be configured to run DHCP on a single interface,
we do not need a script that waits for more than one interface.

Closes #8116.

Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
---
 package/skeleton/S39wait-for-network-if | 43 +++++++++++++++++++++++++++++++++
 package/skeleton/skeleton.mk            |  2 ++
 2 files changed, 45 insertions(+)
 create mode 100644 package/skeleton/S39wait-for-network-if

Comments

Arnout Vandecappelle Oct. 3, 2015, 1:51 p.m. UTC | #1
On 03-10-15 14:31, Yann E. MORIN wrote:
> On some machines, the network interface is slow to appear. For example,
> on the Raspberry Pi, the network interface eth0 is an ethernet-over-USB,
> and our standard boot process is too fast, so our network startup script
> is called before the USB bus is compeltely enumerated, thus it can't
> configure eth0.
> 
> If Buildroot is configured to do a DHCP on an interface, install a
> startup script, just before S40network, that waits for that interface.
> 
> Since Buildroot can only be configured to run DHCP on a single interface,
> we do not need a script that waits for more than one interface.
> 
> Closes #8116.
> 
> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
> ---
>  package/skeleton/S39wait-for-network-if | 43 +++++++++++++++++++++++++++++++++

 Argh, you're adding an init script to skeleton! That's evil(TM)! :-)

 Seriously, this should be part of package/initscripts/init.d/S40network instead.

>  package/skeleton/skeleton.mk            |  2 ++
>  2 files changed, 45 insertions(+)
>  create mode 100644 package/skeleton/S39wait-for-network-if
> 
> diff --git a/package/skeleton/S39wait-for-network-if b/package/skeleton/S39wait-for-network-if
> new file mode 100644
> index 0000000..010026e
> --- /dev/null
> +++ b/package/skeleton/S39wait-for-network-if
> @@ -0,0 +1,43 @@
> +#!/bin/sh
> +
> +# In case we have a slow-to-appear interface (e.g. eth-over-USB),
> +# and we need to configure it, wait until it appears. But not too
> +# long either. WAIT_DELAY is in seconds.
> +WAIT_DELAY=15
> +
> +wait_for_IF() {
> +    IF="$(sed -r -e '/^auto lo/d;' \

 I believe the ; are redundant when you use -e (at least that's what we do in
other cases).

> +                 -e '/^auto (.+)$/!d;' \
> +                 -e 's//\1/;' \

 This one got me looking at the sed man page and I'm still surprised that it
works. Basically, this s command is reusing the same address as given on the
previous line, but without the ! modifier, right?


 Regards,
 Arnout

> +                 /etc/network/interfaces
> +         )"
> +    if [ -z "${IF}" -o -e "/sys/class/net/${IF}" ]; then
> +        return 0
> +    fi
> +    printf "Waiting for interface %s to appear" "${IF}"
> +    wait=${WAIT_DELAY}
> +    while [ ${wait} -gt 0 ]; do
> +        if [ -e "/sys/class/net/${IF}" ]; then
> +            printf " yes\n"
> +            return 0
> +        fi
> +        sleep 1
> +        printf "."
> +        : $((wait--))
> +    done
> +    printf " no.\n"
> +    return 1
> +}
> +
> +case "$1" in
> +  start)
> +	wait_for_IF
> +	;;
> +  stop)
> +	;;
> +  restart)
> +	"$0" start
> +	;;
> +  *)
> +	echo "Usage: $0 {start|stop|restart}"
> +esac
> diff --git a/package/skeleton/skeleton.mk b/package/skeleton/skeleton.mk
> index 48e7085..733b86f 100644
> --- a/package/skeleton/skeleton.mk
> +++ b/package/skeleton/skeleton.mk
> @@ -76,6 +76,8 @@ define SET_NETWORK_DHCP
>  		echo "auto $(NETWORK_DHCP_IFACE)";                   \
>  		echo "iface $(NETWORK_DHCP_IFACE) inet dhcp";        \
>  	) >> $(TARGET_DIR)/etc/network/interfaces
> +	$(INSTALL) -D -m 0755 package/skeleton/S39wait-for-network-if \
> +		$(TARGET_DIR)/etc/init.d/S39wait-for-network-if
>  endef
>  endif
>  
>
Peter Korsgaard Oct. 3, 2015, 1:59 p.m. UTC | #2
>>>>> "Yann" == Yann E MORIN <yann.morin.1998@free.fr> writes:

 > On some machines, the network interface is slow to appear. For example,
 > on the Raspberry Pi, the network interface eth0 is an ethernet-over-USB,
 > and our standard boot process is too fast, so our network startup script
 > is called before the USB bus is compeltely enumerated, thus it can't
 > configure eth0.

 > If Buildroot is configured to do a DHCP on an interface, install a
 > startup script, just before S40network, that waits for that interface.

 > Since Buildroot can only be configured to run DHCP on a single interface,
 > we do not need a script that waits for more than one interface.

 > Closes #8116.

A more generic solution for dynamic changes to network interfaces is to
NOT mark them as auto and instead use ifplugd -M <interface>.

 > Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
 > ---
 >  package/skeleton/S39wait-for-network-if | 43 +++++++++++++++++++++++++++++++++
 >  package/skeleton/skeleton.mk            |  2 ++
 >  2 files changed, 45 insertions(+)
 >  create mode 100644 package/skeleton/S39wait-for-network-if

 > diff --git a/package/skeleton/S39wait-for-network-if b/package/skeleton/S39wait-for-network-if
 > new file mode 100644
 > index 0000000..010026e
 > --- /dev/null
 > +++ b/package/skeleton/S39wait-for-network-if
 > @@ -0,0 +1,43 @@
 > +#!/bin/sh
 > +
 > +# In case we have a slow-to-appear interface (e.g. eth-over-USB),
 > +# and we need to configure it, wait until it appears. But not too
 > +# long either. WAIT_DELAY is in seconds.
 > +WAIT_DELAY=15
 > +
 > +wait_for_IF() {
 > +    IF="$(sed -r -e '/^auto lo/d;' \
 > +                 -e '/^auto (.+)$/!d;' \
 > +                 -e 's//\1/;' \
 > +                 /etc/network/interfaces
 > +         )"

This assumes we have at most 1 interface to wait for.

Perhaps we could instead do something like (untested):

IFACES=$(awk '/^auto/ { print $2 }' /tmp/interfaces)

for i in $(seq $WAIT_DELAY); do
    for IFACE in $IFACES; do
        if [ ! -e "/tmp/$IFACE" ]; then
           sleep 1
           continue 2
        fi
    done

    echo "ok"; exit 0
done

echo "timeout"; exit 1
Peter Korsgaard Oct. 3, 2015, 2:01 p.m. UTC | #3
>>>>> "Peter" == Peter Korsgaard <peter@korsgaard.com> writes:

 >> +wait_for_IF() {
 >> +    IF="$(sed -r -e '/^auto lo/d;' \
 >> +                 -e '/^auto (.+)$/!d;' \
 >> +                 -e 's//\1/;' \
 >> +                 /etc/network/interfaces
 >> +         )"

 > This assumes we have at most 1 interface to wait for.

 > Perhaps we could instead do something like (untested):

 > IFACES=$(awk '/^auto/ { print $2 }' /tmp/interfaces)

That should naturally be /etc/network/interfaces

 > for i in $(seq $WAIT_DELAY); do
 >     for IFACE in $IFACES; do
 >         if [ ! -e "/tmp/$IFACE" ]; then

and /sys/class/net/$IFACE

See, I did actually do a quick test after all ;)
Thomas Petazzoni Oct. 3, 2015, 3:47 p.m. UTC | #4
Hello,

On Sat,  3 Oct 2015 14:31:45 +0100, Yann E. MORIN wrote:

> +    printf "Waiting for interface %s to appear" "${IF}"
> +    wait=${WAIT_DELAY}
> +    while [ ${wait} -gt 0 ]; do
> +        if [ -e "/sys/class/net/${IF}" ]; then
> +            printf " yes\n"
> +            return 0
> +        fi
> +        sleep 1
> +        printf "."
> +        : $((wait--))
> +    done

One thing that I really like in Buildroot is that by default, it
generates you a system that boots really fast. People often don't have
to do anything special with Buildroot to make it boot fast. So having a
shell script that is installed by default and does a "sleep 1" in a
loop is not very nice :-/

Though I agree that it will only slow the boot on systems where the
network interfaces are not available immediately at boot time.

Thomas
Maxime Hadjinlian Oct. 3, 2015, 6:29 p.m. UTC | #5
On Sat, Oct 3, 2015 at 5:47 PM, Thomas Petazzoni <
thomas.petazzoni@free-electrons.com> wrote:

> Hello,
>
> On Sat,  3 Oct 2015 14:31:45 +0100, Yann E. MORIN wrote:
>
> > +    printf "Waiting for interface %s to appear" "${IF}"
> > +    wait=${WAIT_DELAY}
> > +    while [ ${wait} -gt 0 ]; do
> > +        if [ -e "/sys/class/net/${IF}" ]; then
> > +            printf " yes\n"
> > +            return 0
> > +        fi
> > +        sleep 1
> > +        printf "."
> > +        : $((wait--))
> > +    done
>
> One thing that I really like in Buildroot is that by default, it
> generates you a system that boots really fast. People often don't have
> to do anything special with Buildroot to make it boot fast. So having a
> shell script that is installed by default and does a "sleep 1" in a
> loop is not very nice :-/
>
> Though I agree that it will only slow the boot on systems where the
> network interfaces are not available immediately at boot time.
>
I have that trouble too but instead of doing a sleep 1, I "hammer" the
system with sleep 0.1 or usleep 25 if it's available (even usleep 1 can
work, since it's not RT, it takes around 10ms).
This way it's almost transparent and add the necessary requirements before
going on with the boot.

>
> Thomas
> --
> Thomas Petazzoni, CTO, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com
> _______________________________________________
> buildroot mailing list
> buildroot@busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
>
Arnout Vandecappelle Oct. 3, 2015, 6:43 p.m. UTC | #6
On 03-10-15 19:29, Maxime Hadjinlian wrote:
> 
> 
> On Sat, Oct 3, 2015 at 5:47 PM, Thomas Petazzoni
> <thomas.petazzoni@free-electrons.com
> <mailto:thomas.petazzoni@free-electrons.com>> wrote:
> 
>     Hello,
> 
>     On Sat,  3 Oct 2015 14:31:45 +0100, Yann E. MORIN wrote:
> 
>     > +    printf "Waiting for interface %s to appear" "${IF}"
>     > +    wait=${WAIT_DELAY}
>     > +    while [ ${wait} -gt 0 ]; do
>     > +        if [ -e "/sys/class/net/${IF}" ]; then
>     > +            printf " yes\n"
>     > +            return 0
>     > +        fi
>     > +        sleep 1
>     > +        printf "."
>     > +        : $((wait--))
>     > +    done
> 
>     One thing that I really like in Buildroot is that by default, it
>     generates you a system that boots really fast. People often don't have
>     to do anything special with Buildroot to make it boot fast. So having a
>     shell script that is installed by default and does a "sleep 1" in a
>     loop is not very nice :-/
> 
>     Though I agree that it will only slow the boot on systems where the
>     network interfaces are not available immediately at boot time.
> 
> I have that trouble too but instead of doing a sleep 1, I "hammer" the system
> with sleep 0.1 or usleep 25 if it's available (even usleep 1 can work, since
> it's not RT, it takes around 10ms).

 Since sysv init is not parallel, you're not even hammering the system since
nothing else is going on except perhaps some hotplug callbacks.

 Regards,
 Arnout

> This way it's almost transparent and add the necessary requirements before going
> on with the boot.
> 
> 
>     Thomas
>     --
>     Thomas Petazzoni, CTO, Free Electrons
>     Embedded Linux, Kernel and Android engineering
>     http://free-electrons.com
>     _______________________________________________
>     buildroot mailing list
>     buildroot@busybox.net <mailto:buildroot@busybox.net>
>     http://lists.busybox.net/mailman/listinfo/buildroot
> 
> 
> 
> 
> _______________________________________________
> buildroot mailing list
> buildroot@busybox.net
> http://lists.busybox.net/mailman/listinfo/buildroot
>
Maxime Hadjinlian Oct. 3, 2015, 6:46 p.m. UTC | #7
On Sat, Oct 3, 2015 at 8:43 PM, Arnout Vandecappelle <arnout@mind.be> wrote:

> On 03-10-15 19:29, Maxime Hadjinlian wrote:
> >
> >
> > On Sat, Oct 3, 2015 at 5:47 PM, Thomas Petazzoni
> > <thomas.petazzoni@free-electrons.com
> > <mailto:thomas.petazzoni@free-electrons.com>> wrote:
> >
> >     Hello,
> >
> >     On Sat,  3 Oct 2015 14:31:45 +0100, Yann E. MORIN wrote:
> >
> >     > +    printf "Waiting for interface %s to appear" "${IF}"
> >     > +    wait=${WAIT_DELAY}
> >     > +    while [ ${wait} -gt 0 ]; do
> >     > +        if [ -e "/sys/class/net/${IF}" ]; then
> >     > +            printf " yes\n"
> >     > +            return 0
> >     > +        fi
> >     > +        sleep 1
> >     > +        printf "."
> >     > +        : $((wait--))
> >     > +    done
> >
> >     One thing that I really like in Buildroot is that by default, it
> >     generates you a system that boots really fast. People often don't
> have
> >     to do anything special with Buildroot to make it boot fast. So
> having a
> >     shell script that is installed by default and does a "sleep 1" in a
> >     loop is not very nice :-/
> >
> >     Though I agree that it will only slow the boot on systems where the
> >     network interfaces are not available immediately at boot time.
> >
> > I have that trouble too but instead of doing a sleep 1, I "hammer" the
> system
> > with sleep 0.1 or usleep 25 if it's available (even usleep 1 can work,
> since
> > it's not RT, it takes around 10ms).
>
>  Since sysv init is not parallel, you're not even hammering the system
> since
> nothing else is going on except perhaps some hotplug callbacks.
>
sysv is not, but the shell is. The scripts are started in background and
then I simply use wait

>
>  Regards,
>  Arnout
>
> > This way it's almost transparent and add the necessary requirements
> before going
> > on with the boot.
> >
> >
> >     Thomas
> >     --
> >     Thomas Petazzoni, CTO, Free Electrons
> >     Embedded Linux, Kernel and Android engineering
> >     http://free-electrons.com
> >     _______________________________________________
> >     buildroot mailing list
> >     buildroot@busybox.net <mailto:buildroot@busybox.net>
> >     http://lists.busybox.net/mailman/listinfo/buildroot
> >
> >
> >
> >
> > _______________________________________________
> > buildroot mailing list
> > buildroot@busybox.net
> > http://lists.busybox.net/mailman/listinfo/buildroot
> >
>
>
> --
> Arnout Vandecappelle                          arnout at mind be
> Senior Embedded Software Architect            +32-16-286500
> Essensium/Mind                                http://www.mind.be
> G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
> LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
> GPG fingerprint:  7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF
>
Peter Korsgaard Oct. 4, 2015, 8:23 a.m. UTC | #8
>>>>> "Thomas" == Thomas Petazzoni <thomas.petazzoni@free-electrons.com> writes:

 > Hello,
 > On Sat,  3 Oct 2015 14:31:45 +0100, Yann E. MORIN wrote:

 >> +    printf "Waiting for interface %s to appear" "${IF}"
 >> +    wait=${WAIT_DELAY}
 >> +    while [ ${wait} -gt 0 ]; do
 >> +        if [ -e "/sys/class/net/${IF}" ]; then
 >> +            printf " yes\n"
 >> +            return 0
 >> +        fi
 >> +        sleep 1
 >> +        printf "."
 >> +        : $((wait--))
 >> +    done

 > One thing that I really like in Buildroot is that by default, it
 > generates you a system that boots really fast. People often don't have
 > to do anything special with Buildroot to make it boot fast. So having a
 > shell script that is installed by default and does a "sleep 1" in a
 > loop is not very nice :-/

 > Though I agree that it will only slow the boot on systems where the
 > network interfaces are not available immediately at boot time.

Or where you misconfigured /etc/network/interfaces or forgot to enable
the needed drivers in the kernel, but yeah.

But yes, using something like ifplugd to handle the interface when it
shows up (or link state changes) is certainly nicer than just waiting.
Peter Korsgaard Oct. 16, 2015, 9:42 a.m. UTC | #9
>>>>> "Peter" == Peter Korsgaard <peter@korsgaard.com> writes:

>>>>> "Yann" == Yann E MORIN <yann.morin.1998@free.fr> writes:
 >> On some machines, the network interface is slow to appear. For example,
 >> on the Raspberry Pi, the network interface eth0 is an ethernet-over-USB,
 >> and our standard boot process is too fast, so our network startup script
 >> is called before the USB bus is compeltely enumerated, thus it can't
 >> configure eth0.

 >> If Buildroot is configured to do a DHCP on an interface, install a
 >> startup script, just before S40network, that waits for that interface.

 >> Since Buildroot can only be configured to run DHCP on a single interface,
 >> we do not need a script that waits for more than one interface.

 >> Closes #8116.

 > This assumes we have at most 1 interface to wait for.

 > Perhaps we could instead do something like (untested):

 > IFACES=$(awk '/^auto/ { print $2 }' /tmp/interfaces)

 > for i in $(seq $WAIT_DELAY); do
 >     for IFACE in $IFACES; do
 >         if [ ! -e "/tmp/$IFACE" ]; then
 >            sleep 1
 >            continue 2
 >         fi
 >     done

 >     echo "ok"; exit 0
 > done

 > echo "timeout"; exit 1

Committed after moving it to S40network and changing the implementation
to support multiple interaces, thanks.
Jérôme Pouiller Oct. 19, 2015, 8:47 a.m. UTC | #10
Hello Yann,

On Saturday 03 October 2015 14:31:45 Yann E. MORIN wrote:
> On some machines, the network interface is slow to appear. For
> example, on the Raspberry Pi, the network interface eth0 is an
> ethernet-over-USB, and our standard boot process is too fast, so our
> network startup script is called before the USB bus is compeltely
> enumerated, thus it can't configure eth0.
> 
> If Buildroot is configured to do a DHCP on an interface, install a
> startup script, just before S40network, that waits for that interface.
> 
> Since Buildroot can only be configured to run DHCP on a single
> interface, we do not need a script that waits for more than one
> interface.
> 
> Closes #8116.
> 
> Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
> ---
>  package/skeleton/S39wait-for-network-if | 43
> +++++++++++++++++++++++++++++++++ package/skeleton/skeleton.mk       
>     |  2 ++
>  2 files changed, 45 insertions(+)
>  create mode 100644 package/skeleton/S39wait-for-network-if
> 
> diff --git a/package/skeleton/S39wait-for-network-if
> b/package/skeleton/S39wait-for-network-if new file mode 100644
> index 0000000..010026e
> --- /dev/null
> +++ b/package/skeleton/S39wait-for-network-if
> @@ -0,0 +1,43 @@
> +#!/bin/sh
> +
> +# In case we have a slow-to-appear interface (e.g. eth-over-USB),
> +# and we need to configure it, wait until it appears. But not too
> +# long either. WAIT_DELAY is in seconds.
> +WAIT_DELAY=15
> +
> +wait_for_IF() {
> +    IF="$(sed -r -e '/^auto lo/d;' \
> +                 -e '/^auto (.+)$/!d;' \
> +                 -e 's//\1/;' \
> +                 /etc/network/interfaces
> +         )"
> +    if [ -z "${IF}" -o -e "/sys/class/net/${IF}" ]; then
> +        return 0
> +    fi
> +    printf "Waiting for interface %s to appear" "${IF}"
> +    wait=${WAIT_DELAY}
> +    while [ ${wait} -gt 0 ]; do
> +        if [ -e "/sys/class/net/${IF}" ]; then
> +            printf " yes\n"
> +            return 0
> +        fi
> +        sleep 1
> +        printf "."
> +        : $((wait--))
> +    done
> +    printf " no.\n"
> +    return 1
> +}
> +
> +case "$1" in
> +  start)
> +	wait_for_IF
> +	;;
> +  stop)
> +	;;
> +  restart)
> +	"$0" start
> +	;;
> +  *)
> +	echo "Usage: $0 {start|stop|restart}"
> +esac
I am a bit late to do the review, but why not add a script in 
/etc/network/if-pre-up.d ? For example (notice $IFACE and $IF_MAXWAIT 
are set by ifupdown):

#! /bin/sh
if [ "${IF_MAXWAIT}" ]; then
    printf "Waiting for interface %s to appear" "${IFACE}"
    while [ ${IF_MAXWAIT} -gt 0 ]; do
        if [ -e "/sys/class/net/${IFACE}" ]; then
            printf " yes\n"
            exit 0
        fi
        sleep 1
        printf "."
        : $((wait--))
    done
    printf " no.\n"
    exit 1
fi

Next, interface would use "maxwait" property in /etc/network/interface:

auto eth0
iface eth0 inet dhcp
    maxwait 15

BR,
Peter Korsgaard Oct. 19, 2015, 10:15 a.m. UTC | #11
>>>>> "Jérôme" == Jérôme Pouiller <jezz@sysmic.org> writes:

Hi,

> I am a bit late to do the review, but why not add a script in 
 > /etc/network/if-pre-up.d ? For example (notice $IFACE and $IF_MAXWAIT 
 > are set by ifupdown):

 > #! /bin/sh
 > if [ "${IF_MAXWAIT}" ]; then
 >     printf "Waiting for interface %s to appear" "${IFACE}"
 >     while [ ${IF_MAXWAIT} -gt 0 ]; do
 >         if [ -e "/sys/class/net/${IFACE}" ]; then
 >             printf " yes\n"
 >             exit 0
 >         fi
 >         sleep 1
 >         printf "."
 >         : $((wait--))
 >     done
 >     printf " no.\n"
 >     exit 1
 > fi

That's certainly also an option. Care to send a patch reworking the
logic in S40network to a pre-up.d hook?

 > Next, interface would use "maxwait" property in /etc/network/interface:

 > auto eth0
 > iface eth0 inet dhcp
 >     maxwait 15

Then our BR2_SYSTEM_DHCP logic should probably also be adapted to add
'maxwait 15' by default.

Thanks!
Jérôme Pouiller Oct. 19, 2015, 10:22 a.m. UTC | #12
On Monday 19 October 2015 12:15:40 Peter Korsgaard wrote:
> >>>>> "Jérôme" == Jérôme Pouiller <jezz@sysmic.org> writes:
> Hi,
> 
> > I am a bit late to do the review, but why not add a script in
> > 
>  > /etc/network/if-pre-up.d ? For example (notice $IFACE and
>  > $IF_MAXWAIT
>  > are set by ifupdown):
>  > 
>  > #! /bin/sh
>  > if [ "${IF_MAXWAIT}" ]; then
>  > 
>  >     printf "Waiting for interface %s to appear" "${IFACE}"
>  >     while [ ${IF_MAXWAIT} -gt 0 ]; do
>  >     
>  >         if [ -e "/sys/class/net/${IFACE}" ]; then
>  >         
>  >             printf " yes\n"
>  >             exit 0
>  >         
>  >         fi
>  >         sleep 1
>  >         printf "."
>  >         
>  >         : $((wait--))
>  >     
>  >     done
>  >     printf " no.\n"
>  >     exit 1
>  > 
>  > fi
> 
> That's certainly also an option. Care to send a patch reworking the
> logic in S40network to a pre-up.d hook?
Ok, I will.
diff mbox

Patch

diff --git a/package/skeleton/S39wait-for-network-if b/package/skeleton/S39wait-for-network-if
new file mode 100644
index 0000000..010026e
--- /dev/null
+++ b/package/skeleton/S39wait-for-network-if
@@ -0,0 +1,43 @@ 
+#!/bin/sh
+
+# In case we have a slow-to-appear interface (e.g. eth-over-USB),
+# and we need to configure it, wait until it appears. But not too
+# long either. WAIT_DELAY is in seconds.
+WAIT_DELAY=15
+
+wait_for_IF() {
+    IF="$(sed -r -e '/^auto lo/d;' \
+                 -e '/^auto (.+)$/!d;' \
+                 -e 's//\1/;' \
+                 /etc/network/interfaces
+         )"
+    if [ -z "${IF}" -o -e "/sys/class/net/${IF}" ]; then
+        return 0
+    fi
+    printf "Waiting for interface %s to appear" "${IF}"
+    wait=${WAIT_DELAY}
+    while [ ${wait} -gt 0 ]; do
+        if [ -e "/sys/class/net/${IF}" ]; then
+            printf " yes\n"
+            return 0
+        fi
+        sleep 1
+        printf "."
+        : $((wait--))
+    done
+    printf " no.\n"
+    return 1
+}
+
+case "$1" in
+  start)
+	wait_for_IF
+	;;
+  stop)
+	;;
+  restart)
+	"$0" start
+	;;
+  *)
+	echo "Usage: $0 {start|stop|restart}"
+esac
diff --git a/package/skeleton/skeleton.mk b/package/skeleton/skeleton.mk
index 48e7085..733b86f 100644
--- a/package/skeleton/skeleton.mk
+++ b/package/skeleton/skeleton.mk
@@ -76,6 +76,8 @@  define SET_NETWORK_DHCP
 		echo "auto $(NETWORK_DHCP_IFACE)";                   \
 		echo "iface $(NETWORK_DHCP_IFACE) inet dhcp";        \
 	) >> $(TARGET_DIR)/etc/network/interfaces
+	$(INSTALL) -D -m 0755 package/skeleton/S39wait-for-network-if \
+		$(TARGET_DIR)/etc/init.d/S39wait-for-network-if
 endef
 endif