4

I'm trying to use network namespaces to achieve VRF behavior (virtual routing and forwarding) for network isolation. Essentially I have a server application (C/C++) running on a TCP port in the default namespace. What I'd like to do is use network namespaces to create isolated VRF's using VLANs, and then have that application running in the default namespace be able to spawn a thread to each namespace to listen on that same port per namespace.

I have the network side figured out, I just can't see how I can spawn a thread (prefer to use pthread's instead of clone() if possible), call setns() on one of those namespaces, and then bind to the same port inside the namespace. Here's what I'm doing to create the namespaces and bridges (limiting to one namespace here for simplicity):

# ip netns add ns_vlan100
# ip link add link eno1 eno1.100 type vlan id 100

# ip link add veth0 type veth peer name veth_vlan100
# ip link set veth0 netns ns_vlan100

# ip netns exec ns_vlan100 ip link set dev veth0 up
# ip link set dev veth_vlan100 up

# brctl addbr bridge_vlan100
# brctl addif bridge_vlan100 eno1.100
# brctl addif bridge_vlan100 veth_vlan100

# ip link set dev bridge_vlan100 up
# ip link set dev eno1.100 up

# ip netns exec ns_vlan100 ifconfig veth0 10.10.10.1 netmask 255.255.255.0 up
# ip netns exec ns_vlan100 ip route add default via 10.10.10.1

With this, I can create a VLAN on a peer machine (no containers) and ping 10.10.10.1 without issue. So I know the links are good. What I want to do is then have my existing application be able to spawn a thread in C or C++ (pthreads are heavily preferred), and that thread call setns() with something to put it into namespace ns_vlan100, so I can then bind to the same port for my application, just inside that namespace.

I can't seem to figure out how to do this. Any help is much appreciated.

chrk
  • 4,037
  • 2
  • 39
  • 47
pjw
  • 41
  • 1
  • 4
  • 1
    Actually yes. Apologies for not following up on this. The trick was to make sure at least the loopback interface is up inside the namespace. Then the application can call setns() with the new namespace information (gleaned from opening /run/netns/ and using that fd), and bind to INADDR_ANY and the port you wish to listen on. That way you don't need to time the network interface coming up first, it will just bind when the interface comes online. – pjw Jan 05 '16 at 23:11
  • Thanks, to clarify does setns work on pthreads (e.g. can I have separate network namespaces per pthread or does setns change the namespace for the entire process? – David Mokon Bond Jan 06 '16 at 16:01
  • 1
    Nevermind. I made a test progam and seems it is per pthread: void thread(){ int fd = open("/run/netns/blue", O_RDONLY); setns(fd, CLONE_NEWNET); system("ip link list"); sleep(3); } int main() { std::thread t(thread); t.join(); system("ip link list"); return 0; } – David Mokon Bond Jan 06 '16 at 16:22
  • 3
    Correct, it is per pthread. One trick too, since you can open /run/netns/ for created namespaces, but you don't have an inherent filehandle for the default namespace there, open /proc/1/ns/net and store that fd. Since init should never be in a different namespace than the default one (unless you're using PID namespaces), then you can return to the default namespace with setns() if you need to switch back for whatever reason. – pjw Jan 07 '16 at 16:44

0 Answers0