概述

wfb_tun 是 WFB-ng 的 TUN(网络隧道)设备桥接程序,负责在 Linux TUN 虚拟网卡和 UDP socket 之间双向转发 IPv4 数据包。它使得可以通过 WFB-ng 无线链路传输任意的 IP 流量,实现通用的 IPv4 over WiFi 隧道功能。

该程序使用 libevent 事件库实现非阻塞 I/O,支持数据包聚合以减少小包的无线开销,并内置心跳机制维持链路活跃。

工作原理

1
2
TUN 虚拟网卡 <===> wfb_tun <===> UDP socket <===> wfb_tx/wfb_rx <===> 无线链路
(IP包) (桥接+聚合) (UDP封装) (FEC+加密) (空中传输)

数据流向

  1. TUN -> Socket(发送方向):从 TUN 设备读取 IP 数据包,添加长度头部进行聚合,通过 UDP 发送到对端
  2. Socket -> TUN(接收方向):从 UDP socket 接收聚合的数据包,解析长度头部提取原始 IP 包,写入 TUN 设备

数据包格式

1
2
3
4
5
+------------------+------------------+------------------+
| tun_packet_hdr_t | IP Packet | tun_packet_hdr_t | ...
| (2 bytes: len) | (variable) | (2 bytes: len) |
+------------------+------------------+------------------+
^ Entire batch sent as single UDP packet (max MTU=1445 bytes)

使用方式

1
2
wfb_tun [-t tun_name] [-a tun_addr] [-c peer_addr] [-u peer_port] \
[-l listen_port] [-T agg_timeout_ms]

参数详解

参数 说明 默认值
-t tun_name TUN 设备名称。创建/使用的虚拟网卡接口名。程序会自动创建设备并配置。 wfb-tun
-a tun_addr TUN 设备的 IP 地址(CIDR 格式)。设置虚拟网卡的 IP 地址和子网掩码,同时自动将接口设为 UP 状态并配置 MTU。 10.5.0.2/24
-c peer_addr 对端 UDP 地址。发送方向的目标 IP 地址。接收方向的 socket 绑定到所有接口(INADDR_ANY),不限制来源。 127.0.0.1
-u peer_port 对端 UDP 端口号。发送方向的目标端口。通常指向本地 wfb_tx/wfb_rx 的监听端口。 5801
-l listen_port 本地 UDP 监听端口号。接收方向的绑定端口。wfb_rx 输出的数据会发送到这个端口。 5800
-T agg_timeout_ms 聚合超时时间(毫秒)。小数据包在发送前等待此时间以聚合更多数据到一个 UDP 包中,减少无线开销。设为 0 表示不聚合、立即发送每个包。 5

内部机制

MTU 配置

  • 无线侧 MTU:1445 字节(定义为 MTU
  • TUN 设备 MTU:自动设置为 MTU - sizeof(tun_packet_hdr_t) = 1443 字节
  • 每个 IP 包前面添加 2 字节的长度头部

数据包聚合

1
2
3
4
5
6
7
8
9
10
聚合流程(TUN -> Socket):
1. 从 TUN 读取 IP 包,添加 tun_packet_hdr_t 头部
2. 如果缓冲区 <= MTU,继续累积更多包
3. 当缓冲区 >= MTU 或达到 agg_timeout_ms 超时,发送整个批次
4. 如果 agg_timeout_ms = 0,每个包立即单独发送

聚合好处:
- 减少小包数量,降低 FEC 编码开销
- 提高无线链路的有效利用率
- 适合 mavlink 等小数据包场景

心跳机制

  • 间隔:每 500 毫秒(PING_INTERVAL_MS
  • 条件:仅当过去 500ms 内没有发送任何数据时,才发送空包作为心跳
  • 目的:保持链路活跃,防止 NAT/防火墙超时断开连接
  • 接收端处理:收到长度为 0 的包直接丢弃(识别为心跳)

事件驱动架构

使用 libevent 实现五个核心事件:

事件 触发条件 回调函数 作用
ev_ping 定时器(500ms) ev_ping_cb() 心跳发送
ev_tun_read TUN fd 可读 ev_tun_read_cb() 从 TUN 读取 IP 包并聚合
ev_tun_read_timeout 聚合超时 ev_socket_write_cb() 超时后刷新聚合缓冲区
ev_socket_write socket 可写 ev_socket_write_cb() 发送聚合批次到 UDP
ev_socket_read socket 可读 ev_socket_read_cb() 从 UDP 接收数据并写入 TUN

信号处理

  • SIGINT(Ctrl+C):优雅退出,关闭所有 fd
  • SIGTERM:优雅退出,关闭所有 fd

典型使用场景

1
2
3
4
5
# 创建 TUN 设备,桥接本地 wfb_rx (5801) -> wfb_tun -> wfb_tx (5800)
wfb_tun -t wfb-tun -a 10.5.0.2/24 -c 127.0.0.1 -u 5801 -l 5800

# 在另一端(接收方)同样运行:
wfb_tun -t wfb-tun -a 10.5.0.1/24 -c 127.0.0.1 -u 5801 -l 5800

2. 远程 IP 隧道

1
2
3
4
5
# 无人机端:TUN -> UDP -> wfb_tx -> 无线
wfb_tun -t drone-tun -a 10.0.0.2/24 -c 127.0.0.1 -u 5603 -l 5604

# 地面站端:无线 -> wfb_rx -> UDP -> TUN
wfb_tun -t gs-tun -a 10.0.0.1/24 -c 127.0.0.1 -u 5604 -l 5603

3. 零聚合延迟模式

1
2
# 禁用聚合,每个包立即发送(适合对延迟极度敏感的场景)
wfb_tun -t wfb-tun -a 10.5.0.2/24 -T 0

4. 自定义 TUN 名称和地址

1
2
# 使用自定义设备名和 IP 配置
wfb_tun -t mytun0 -a 192.168.100.1/16 -c 10.0.0.5 -u 9001 -l 9000

与 wfb_tx/wfb_rx 的配合

完整的 mavlink/IP 隧道链路配置:

无人机端(发送方)

1
2
3
4
5
6
7
8
9
# TUN -> UDP(5603) -> wfb_tx -> 无线
wfb_tun -t wfb-tun -a 10.65.0.2/24 -c 127.0.0.1 -u 5603

# 接收来自 wfb_rx 的数据 -> TUN
# (如果需要双向通信)
wfb_tun -t wfb-tun-rx -a 10.66.0.2/24 -c 127.0.0.1 -u 5605 -l 5604

# wfb_tx 发送 mavlink/tunnel 数据
wfb_tx -K /etc/drone.key -u 5603 -i 1 wlan0

地面站端(接收方)

1
2
3
4
5
# 无线 -> wfb_rx -> UDP(5603) -> TUN
wfb_tun -t wfb-tun -a 10.65.0.1/24 -c 127.0.0.1 -u 5604 -l 5603

# wfb_rx 接收无线数据并输出到本地 UDP
wfb_rx -K /etc/gs.key -c 127.0.0.1 -u 5603 -i 1 wlan0

注意事项

  1. 需要 root 权限:创建 TUN 设备和配置网络接口需要 CAP_NET_ADMIN 能力,通常以 root 运行或使用 sudo
  2. MTU 限制:通过隧道的 IP 包大小不能超过 1443 字节(减去 tun_packet_hdr_t 头部后)
  3. 仅支持 IPv4:当前实现只处理 IPv4 数据包
  4. 防火墙配置:确保 UDP 端口(listen_port 和 peer_port)在防火墙上开放

依赖库

  • libevent(事件驱动 I/O)
  • Linux TUN/TAP 设备(/dev/net/tun)