I am trying to create virtual network devices in order to test and develop multicast programs. My computer has a single NIC with one Ethernet port, which is connected to the Internet. I want a second (virtual) NIC, connected to a bridge, which has 2 other computers connected to it for testing. In other words:
- Create a virtual NIC.
- Create a virtual bridge/switch.
- Connect the virtual NIC to the virtual bridge.
- Create two additional virtual NIC devices (to be used as remote hosts) and connect them to the virtual bridge.
As I understand it, creating a virtual bridge in Linux implicitly creates and connects a virtual NIC to it, which is accessible as a network interface. I answered a question explaining this here (although I may be wrong).
I know that I could test multicast programs with VMs, but this is quite cumbersome, and my understanding was that with the proper routing tables I should be able to run programs natively if I bind them to the appropriate virtual network device and address. So far, I can't even get pinging to work, much less multicast. This is what I have:
ip link add br0 type bridge
ip link add dum0 type dummy
ip link add dum1 type dummy
ip link set dev dum0 master br0
ip link set dev dum1 master br0
ip addr add 10.0.0.1/24 brd + dev br0
ip addr add 10.0.0.2/24 brd + dev dum0
ip addr add 10.0.0.3/24 brd + dev dum1
ip link set br0 up
ip link set dum0 up
ip link set dum1 up
ip route del 10.0.0.0/24 dev dum0
ip route del 10.0.0.0/24 dev dum1
ip route del broadcast 10.0.0.0 dev dum0
ip route del broadcast 10.0.0.0 dev dum1
ip route del broadcast 10.0.0.255 dev dum0
ip route del broadcast 10.0.0.255 dev dum1
ip route del local 10.0.0.2
ip route del local 10.0.0.3
For convenience, you can use the following to undo that:
ip link del dev dum1
ip link del dev dum0
ip link del dev br0
Upon inspection everything is configured exactly as it would be with physical hardware:
$ ip addr show br0
41: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 56:47:31:fd:10:c0 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.1/24 brd 10.0.0.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::5447:31ff:fefd:10c0/64 scope link
valid_lft forever preferred_lft forever
$ ip addr show dum0
42: dum0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UNKNOWN group default qlen 1000
link/ether 56:47:31:fd:10:c0 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.2/24 brd 10.0.0.255 scope global dum0
valid_lft forever preferred_lft forever
inet6 fe80::5447:31ff:fefd:10c0/64 scope link
valid_lft forever preferred_lft forever
$ ip addr show dum1
43: dum1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UNKNOWN group default qlen 1000
link/ether d2:47:c8:19:4a:60 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global dum1
valid_lft forever preferred_lft forever
inet6 fe80::d047:c8ff:fe19:4a60/64 scope link
valid_lft forever preferred_lft forever
$ ip route show table main
10.0.0.0/24 dev br0 proto kernel scope link src 10.0.0.1
$ ip route show table local
broadcast 10.0.0.0 dev br0 proto kernel scope link src 10.0.0.1
local 10.0.0.1 dev br0 proto kernel scope host src 10.0.0.1
broadcast 10.0.0.255 dev br0 proto kernel scope link src 10.0.0.1
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
$ ip route get to 10.0.0.1
local 10.0.0.1 dev lo src 10.0.0.1 uid 1000
cache <local>
$ ip route get to 10.0.0.2
10.0.0.2 dev br0 src 10.0.0.1 uid 1000
cache
... with one exception: the MAC address of dum0
and br0
is the same. This worries me, because it suggests that my understanding of the bridge device is wrong, that it isn't actually a virtual NIC connected to the bridge device, but instead some sort of weird neither-bridge-nor-NIC that can't be used normally. In any case, I don't think this interferes with the rest of the testing. Routing through the dummy devices doesn't work either.
As for the testing, I can only ping any of the devices through the loopback device (lo
). The routing table correctly routes packets through br0
to dum0
and dum1
, but it returns Destination Host Unreachable
:
$ ping -c 2 10.0.0.1 # br0 through lo OK
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.029 ms
--- 10.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 56ms
rtt min/avg/max/mdev = 0.029/0.041/0.053/0.012 ms
$ ping -c 2 10.0.0.2 # dum0 through br0 BAD
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
From 10.0.0.1 icmp_seq=1 Destination Host Unreachable
From 10.0.0.1 icmp_seq=2 Destination Host Unreachable
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 62ms
pipe 2
$ ping -c 2 -I lo 10.0.0.2 # dum0 through lo OK
ping: Warning: source address might be selected on device other than lo.
PING 10.0.0.2 (10.0.0.2) from x.x.x.x lo: 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.033 ms
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 35ms
rtt min/avg/max/mdev = 0.033/0.040/0.047/0.007 ms
At this point I really don't know what I could be doing wrong. I patched everything through my firewall. I think the only thing are the dummy devices. I tried researching how to "just create a virtual NIC," and that has been extremely frustrating. The ip-link(8)
man page lists literally dozens of possible devices, giving absolutely no idea what they do differently from each other or when you would use them. I can't stress enough how hard I tried to research this, because it seems simple enough, but it is very difficult to find information on it (if you don't know so already).
I have read that dummy devices may simply discard data (from one obscure source and nowhere else), in which case maybe they drop ARP requests and I can't find their MAC address (if that is even necessary in this virtual configuration). I also tried using ip tuntap
(Linux taps), and that didn't work either, but if I understand those correctly, they provide the raw IP packets (for tunnels) or Ethernet frames (for taps) to programs that request them from the kernel, and otherwise drop all data too.
So, what kind of device do I need? Is this even going to work to test multicast programs? Will I be able to bind to the address of a device, send multicast traffic from it, have it sent across the bridge, and received by a multicast program bound to another device address? This has been quite involved, so I appreciate any help and anyone that can read through it. Thanks!
ip netns
(which does a bit more than just network namespaces, but let's say that's the same).