Skip to content

Commit

Permalink
net: Guaranetee the proper ordering of the loopback device. v2
Browse files Browse the repository at this point in the history
I was recently hunting a bug that occurred in network namespace
cleanup.  In looking at the code it became apparrent that we have
and will continue to have cases where if we have anything going
on in a network namespace there will be assumptions that the
loopback device is present.   Things like sending igmp unsubscribe
messages when we bring down network devices invokes the routing
code which assumes that at least the loopback driver is present.

Therefore to avoid magic initcall ordering hackery that is hard
to follow and hard to get right insert a call to register the
loopback device directly from net_dev_init().    This guarantes
that the loopback device is the first device registered and
the last network device to go away.

But do it carefully so we register the loopback device after
we clear dev_boot_phase.

Signed-off-by: Eric W. Biederman <ebiederm@maxwell.aristanetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric W. Biederman authored and davem330 committed Nov 8, 2008
1 parent 5d6d480 commit 505d4f7
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
13 changes: 2 additions & 11 deletions drivers/net/loopback.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,8 @@ static __net_exit void loopback_net_exit(struct net *net)
unregister_netdev(dev);
}

static struct pernet_operations __net_initdata loopback_net_ops = {
/* Registered in net/core/dev.c */
struct pernet_operations __net_initdata loopback_net_ops = {
.init = loopback_net_init,
.exit = loopback_net_exit,
};

static int __init loopback_init(void)
{
return register_pernet_device(&loopback_net_ops);
}

/* Loopback is special. It should be initialized before any other network
* device and network subsystem.
*/
fs_initcall(loopback_init);
1 change: 1 addition & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,7 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
return 0;
}

extern struct pernet_operations __net_initdata loopback_net_ops;
#endif /* __KERNEL__ */

#endif /* _LINUX_DEV_H */
22 changes: 17 additions & 5 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4909,9 +4909,6 @@ static int __init net_dev_init(void)
if (register_pernet_subsys(&netdev_net_ops))
goto out;

if (register_pernet_device(&default_device_ops))
goto out;

/*
* Initialise the packet receive queues.
*/
Expand All @@ -4928,10 +4925,25 @@ static int __init net_dev_init(void)
queue->backlog.weight = weight_p;
}

netdev_dma_register();

dev_boot_phase = 0;

/* The loopback device is special if any other network devices
* is present in a network namespace the loopback device must
* be present. Since we now dynamically allocate and free the
* loopback device ensure this invariant is maintained by
* keeping the loopback device as the first device on the
* list of network devices. Ensuring the loopback devices
* is the first device that appears and the last network device
* that disappears.
*/
if (register_pernet_device(&loopback_net_ops))
goto out;

if (register_pernet_device(&default_device_ops))
goto out;

netdev_dma_register();

open_softirq(NET_TX_SOFTIRQ, net_tx_action);
open_softirq(NET_RX_SOFTIRQ, net_rx_action);

Expand Down

0 comments on commit 505d4f7

Please sign in to comment.