Unable to add interface to network namespace on boot

I have problem with adding a phyisical ethernet interface to a predefined namespace , adding that to interfaces file in pre-up/post-up event do not work. It adds eth to namespace, but ip address and LOWER_UP state never appear. Removing namespace in down event doesnt work either, making restart of networking service impractical: it flags it as failed if namespace already exist, in result interface never comes to "up" state.

auto lo
iface lo inet loopback

#description of other interfaces

auto eth2
iface eth2 inet static
    address 196.10.10.200
    network 196.10.10.0
    gateway 196.10.10.100
    netmask 255.255.255.0
    pre-up ip netns add mynetns
    pre-up ip link set eth2 netns mynetns
    down ip netns delete mynetns

Purpose ofthis is to keep a daemon software runningwhich works only in one interface present. The host contains multiple interfaces. Daemon can be relaunched and is created in upstart.


Solution 1:

Overall OP's attempt will fail: even if the interface is put in the new network namespace, then the address assignment will be attempted in the initial namespace and fail. Only the manual method should be used, and everything configured with pre-up/up/down. Then it's simply juggling around ifupdown.

To avoid de-synchronization between interface state (including namespace existence) and ifupdown state because of previous manual attempts, I added a few || : to prevent failure. Those are not needed once everything is set correctly. As the manual method is still responsible to bring up the interface, a fake interface must still be created in place (but can be deleted later, see at the end of the answer).

I'm using modern syntax shortcut to configure in a namespace. In the past this might not have been available. If needed on a very old system, consider:

ip -n FOO BAR

to be equivalent to:

ip netns exec FOO ip BAR

and replace accordingly.

auto eth2
iface eth2 inet manual
    pre-up ip netns add mynetns || :
    pre-up ip link set eth2 netns mynetns || :
    pre-up ip link add eth2 type dummy || :
    pre-up ip -n mynetns link set eth2 up
    up ip -n mynetns address add 196.10.10.200/24 brd +
    up ip -n mynetns route add default via 196.10.10.100 dev eth2
    down ip link del eth2
    down ip -n mynetns link set eth2 netns 1 # prevents a rogue process to keep the interface "lost"
    down ip netns delete mynetns

With this in place (and in this test the real eth2 faked with a macvlan interface hence @if2):

# ifup eth2
# ip -br link show dev eth2
eth2             UNKNOWN        5a:4e:5c:64:98:92 <BROADCAST,NOARP,UP,LOWER_UP> 
# ip -n mynetns -br link show dev eth2
eth2@if2         UP             12:34:56:78:9a:bc <BROADCAST,MULTICAST,UP,LOWER_UP> 
# ip -n mynetns -br route
default via 196.10.10.100 dev eth2 
196.10.10.0/24 dev eth2 proto kernel scope link src 196.10.10.200 
# ifdown eth2
# ip -br link show dev eth2
eth2@enp2s0      DOWN           12:34:56:78:9a:bc <BROADCAST,MULTICAST> 

If that's an issue to keep a fake eth2 interface, simply replace:

    down ip link del eth2

with:

    up ip link del eth2

That way the dummy interface will be deleted right after its role is over: keep ifupdown happy when it wants to bring the interface up (and then there's no need to delete it later).