Let me describe my setup.
Using Debian. I've got eth0 connected to my home router. A MACVLAN (named m0) is created from eth0. A TAP device (named tap0) is created using tunctl. Finally, a bridge (named br0) is created using bridge-utils and both m0 and tap0 are connected to the bridge.
Using ping, I was able to capture an example ICMP request from tcpdump. First, I used dhclient to get br0 an IP address from the home router. Next, I ping the router from br0. I then capture this packet in tcpdump.
Next, I write to the tap0 interface in Python. Once I get the file object, I copy the example ICMP request from before (it has IP address from br0 to 192.168.1.1, which is home router), convert it to binary, and then write it to the file object.
Using tcpdump, I can see the packet I wrote to the file object in Python appear just as intended -- an ICMP echo request. I can see this packet on every interface in the chain (tap0, br0, m0, eth0).
Here's the problem I'm trying to tackle. I can see the ICMP echo reply on every interface in the chain, except tap0 (br0, m0, eth0) using tcpdump. Ideally, I want to read from the file object in Python to see the ICMP echo reply there. It makes sense that what I have doesn't work, since the bridge is the one with the IP address in the reply packet. How do I modify this setup such that I can both read and write from tap0?
dhclient doesn't work with tap0, however. The only way I could imagine this working is somehow finding a way to give tap0 an IP address that is known by the router. I hope I don't have to implement a dhclient in Python that writes through the tap0 file object.
This setup was inspired by the networking needed in VMs. I'm trying to experiment with the system infrastructure necessary for a user space program to write data to the wire and being able to read the data back from the wire.
Thanks for the responses and sorry for the somewhat lengthy post.
Commands from Terminal to:
- Create macvlan m0:
sudo ip link add link eth0 m0 type macvlan
- Create TAP tap0:
sudo tunctl -u root
- Initialization of network devices:
sudo ip addr add 0.0.0.0 dev m0/tap0
sudo ip link set dev m0/tap0 promisc on
- Create and link bridge to m0 and tap0:
sudo brctl addbr br0
sudo brctl addif br0 tap0/m0
sudo ip link set dev br0 up
sudo dhclient br0
In Python, I'm doing stuff similar to the initialization steps of https://gist.github.com/glacjay/585369
From there I just have a file object referring to the tap0 interface that I open with os.fdopen(TAP0_FD, 'r+b')
and that I can write to and read from, as in the explanation above.