Start with the VLANs, Bonding, Bridging. This is part 2 of 3 in the Advanced Networking in Linux series (4 posts in total). Also in this series: VLANs, Bonding, Bridging, Routing and Firewalling, Overlays and CNI.
Part 1 built Layer 2 stacks on a host. Part 2 moved packets between IP networks. Both assumed one network stack: one set of interfaces, routes, and firewall rules.
This post isolates whole stacks on the same machine. A network namespace is a private view of networking. A veth pair is a cable between views. A bridge, macvlan, or ipvlan is how those cables join a shared domain or a parent NIC.
These are the same primitives containers reuse. This article stays on the kernel tools. Product wiring (Docker drivers, Kubernetes CNI) is the next post.
In this lab, namespaces imitate isolated workloads, not cluster nodes.
The Mental Model
A network namespace (netns) has its own:
- interfaces (including
lo) - addresses and routes
- neighbor tables
- firewall rules
Processes in that namespace only see that stack. The host’s default namespace is just another one — the one you use when you do not call ip netns.
A veth pair is two ends of a virtual Ethernet cable. What goes in one end comes out the other. Put one end in a namespace and leave the other in the host (or in a bridge), and you have a patch cable between stacks.
| |
Part 1’s bridge is how several of those cables share a Layer 2 domain. Part 2’s forwarding is how namespaces on different subnets talk through the host as a router.
Network Namespaces
Create, list, and enter a namespace:
| |
Loopback is down by default in a new namespace:
| |
ip netns identify <pid> shows which namespace a process is in. ip netns delete app removes the namespace when you are done (move or delete interfaces first if needed).
Inside vs outside:
| |
veth Pairs
Create a pair and move one end into app:
| |
Ping both ways:
| |
Attach Like a VM Tap
For a shared Layer 2 domain, put the host end on a bridge instead of addressing it directly — the same pattern as part 1’s VM tap:
| |
The namespace still uses 10.0.0.2/24 on veth-app. From the namespace’s point of view it has one NIC; the bridge is the software switch in the default namespace.
Bridge vs Macvlan vs Ipvlan
Three common ways to hang a namespace (or container) off a parent interface:
| Approach | What the workload looks like | Parent role |
|---|---|---|
| Bridge + veth | Its own MAC on a software switch | Bridge ports; host IP usually on the bridge |
| Macvlan | Its own MAC on the parent NIC’s network | Parent presents multiple MACs upstream |
| Ipvlan | Usually shares the parent’s MAC; L3 (or L2) modes | Parent MAC reused; less MAC churn |
Bridge + veth is the clearest lab model and the classic Docker/libvirt pattern: lots of virtual ports, one switch, host can filter or route at the bridge edge.
Macvlan gives each child a distinct MAC on the real LAN. That is useful when something upstream expects unique MACs, or when you want workloads to look like separate machines on the switch. The tradeoff is MAC visibility: multiple source MACs leave through the parent. Some physical switches, Wi-Fi clients, and cloud networks restrict that. Host↔child communication on macvlan also has its own limitations (the host often cannot talk to macvlan children the way it talks to bridge ports without an extra macvlan in “bridge” mode or similar). Do not treat “enable promiscuous mode on the NIC” as a universal fix; whether the parent needs promiscuous mode depends on driver, mode, and topology.
Ipvlan keeps one MAC on the wire and demultiplexes by IP (L3 mode) or shares L2 carefully (L2 mode). It is often the less painful default on clouds that allow few MACs per NIC or that filter unexpected source MACs.
Temporary macvlan example (child in a namespace):
| |
Temporary ipvlan L3 example:
| |
Prefer bridge+veth when you control the host switch and want simple host↔guest traffic. Prefer ipvlan when the upstream network is MAC-hostile. Prefer macvlan when you truly need distinct MACs and the network allows them.
Practical Lab
Lab A: Two workloads on a point-to-point veth
| |
Lab B: One workload on a bridge, one routed
Reuse part 1’s bridge idea and part 2’s forwarding:
| |
From bridged, ping 10.20.0.1. From routed, ping 10.30.0.1 and, with forwarding and routes, reach 10.20.0.0/24. You have seen L2 isolation (bridge domain) versus L3 isolation (routed namespace) on one machine.
Cleanup sketch:
| |
Deleting a namespace removes interfaces that lived only there; delete host-side leftovers explicitly.
Verification Workflow
| |
Packet capture on the host end of a veth:
| |
Common Mistakes
- Leaving
lodown: Local services and some tooling fail in confusing ways. - Addressing a bridge port instead of the bridge: Same rule as part 1 — IP on
br0, not onveth-hostonce it is enslaved. - veth end stuck in the wrong namespace:
ip linkin the default ns will not show the peer; checkip netns exec … ip link. - Assuming bridged namespace traffic is firewalled like routed traffic: Without
br_netfilter, a pure L2 bridge does not hit the IPforwardchain the way part 2 described. See part 1’s bridge firewall note. - MAC visibility and upstream restrictions (macvlan): Multiple source MACs through the parent can be blocked by cloud or campus networks; host↔macvlan-child communication has separate limitations. Do not start with “turn on promiscuous mode” as the generic diagnosis.
Tooling Notes
Almost everything here is iproute2: ip netns, ip link, ip addr, bridge. No separate “namespace daemon” is required for labs.
Containers runtimes create these objects for you. Understanding the objects first makes docker network and CNI less magical — and that is exactly what the next post builds on.
Further Reading
ip-netns(8)ip-link(8)—veth,macvlan,ipvlan- Linux bridge documentation
Conclusion
Network namespaces give each workload its own stack. Veth pairs connect those stacks. Bridges, macvlan, and ipvlan choose how the connection appears on the host and on the wire.
Containers reuse this model on one host. Clusters need the same idea across hosts — an underlay, often an overlay such as VXLAN, and a contract so the runtime does not hard-code every wiring choice. That story is Linux VXLAN and Why CNI Exists.