I want to exchange Ethernet Packet between two tap device(for implementing TCP/IP protocol stack in usermode).
The problem I encountered is that tap1 and tap2 only can receive broadcast packet through bridge but not point to point packet!
For example, when I send packet from tap1 to tap2,tcmpdump can capture packet on tap1,but tap2 can't receive packet.However,when I set detination address as "ff:ff:ff:ff:ff:ff" or any unknown mac address(this will be trigger broadcast),tap2 will receive packet.
My configuration:
- create two tap device
ip tuntap add mode tap tun1
ip tuntap add mode tap tun2
# assign ip address for implmenting arp protocol
ip addr add 172.19.16.1 dev tun1
ip addr add 172.19.16.2 dev tun2
ip link set tun1 up
ip link set tun2 up
- create a bridge
brctl addbr br0
brctl addif br0 tun1
brctl addif br0 tun2
ip link set br0 up
The following is the state of bridge and tap interface:
macs:
port no mac addr is local? ageing timer
2 46:44:6e:55:9b:c5 yes 0.00
2 46:44:6e:55:9b:c5 yes 0.00
1 f2:6b:68:c9:60:6b yes 0.00
1 f2:6b:68:c9:60:6b yes 0.00
state:
br0
bridge id 8000.46446e559bc5
designated root 8000.46446e559bc5
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 89.77
flags
tun1 (1)
port id 8001 state forwarding
designated root 8000.46446e559bc5 path cost 100
designated bridge 8000.46446e559bc5 message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
tun2 (2)
port id 8002 state forwarding
designated root 8000.46446e559bc5 path cost 100
designated bridge 8000.46446e559bc5 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
The following is my test code:
import fcntl
import os
import if_tun
import ctypes
import struct
from scapy.all import *
from if_tun import IfReq, TUNSETIFF, IFF_TUN
def register_tun(name: str):
fd = os.open("/dev/net/tun",os.O_RDWR)
if fd < 0:
return fd
r = IfReq()
ctypes.memset(ctypes.byref(r), 0, ctypes.sizeof(r))
r.ifr_ifru.ifru_flags = 0x0002 | 0x1000
r.ifr_ifrn.ifrn_name = name.encode("utf-8")
fcntl.ioctl(fd, TUNSETIFF,r)
return fd
if __name__ == "__main__":
name = input("input device name")
fd = register_tun(name)
if fd < 0:
print("error")
if name == "tun2":
while True:
buf = os.read(fd,1024)
print(f"receive {len(buf)} data")
Ether(raw(buf)).show()
mac1 = "f2:6b:68:c9:60:6b"
mac2 = "46:44:6e:55:9b:c5"
while True:
type = input()
a = Ether(dst=mac2,src=mac1)/ARP(pdst="172.19.16.1",psrc="172.19.16.2")
a.show()
print("write:")
print(os.write(fd, raw(a)))
Notes:
- Although device name called tun,it's type is tap
- I run two test code simultaneously, one connect tun1 and other connect tun2. So two device are LOWWER_UP state