当前位置: 首页 > news >正文

Ethernet over UART

TUN vs TAP (one sentence) :

  • TUN = IP-level interface → only L3 packets (IPv4/IPv6)

  • TAP = Ethernet-level interface → full L2 frames (Ethernet header, ARP, etc.)

So TAP is exactly what you want for sending raw Ethernet frames over your own UART transport.

#define _GNU_SOURCE #include <stdio.h> #include <stdint.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <termios.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <linux/if_tun.h> #include <linux/if.h> #include <errno.h> #define MAX_FRAME 2000 //----------------------------------------------- // TAP allocation //----------------------------------------------- int tap_alloc (char *devname) { struct ifreq ifr; int fd = open("/dev/net/tun", O_RDWR); if (fd < 0) { perror("open /dev/net/tun"); exit(1); } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; // TAP = Ethernet frames, no extra header if (*devname) strncpy(ifr.ifr_name, devname, IFNAMSIZ); if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) { perror("TUNSETIFF"); exit(1); } strcpy(devname, ifr.ifr_name); return fd; } //----------------------------------------------- // UART open + config //----------------------------------------------- int uart_open (const char *dev) { int fd = open(dev, O_RDWR | O_NOCTTY); if (fd < 0) { perror("open uart"); exit(1); } struct termios tty; tcgetattr(fd, &tty); cfmakeraw(&tty); cfsetspeed(&tty, B115200); tty.c_cflag |= (CLOCAL | CREAD); tcsetattr(fd, TCSANOW, &tty); return fd; } //----------------------------------------------- // Very simple framing: // [0xAA][len_hi][len_lo][FRAME...] //----------------------------------------------- int uart_send_frame (int uart_fd, uint8_t *data, int len) { uint8_t hdr[3]; hdr[0] = 0xAA; hdr[1] = (len >> 8) & 0xFF; hdr[2] = (len) & 0xFF; write(uart_fd, hdr, 3); write(uart_fd, data, len); return 0; } int uart_recv_frame (int uart_fd, uint8_t *buf, int max) { uint8_t hdr[3]; int n; // Wait for sync byte 0xAA do { n = read(uart_fd, hdr, 1); if (n <= 0) return -1; } while (hdr[0] != 0xAA); // Read length if (read(uart_fd, hdr + 1, 2) != 2) return -1; int len = (hdr[1] << 8) | hdr[2]; if (len > max) return -1; // Read frame n = read(uart_fd, buf, len); if (n != len) return -1; return len; } //----------------------------------------------- // Main loop //----------------------------------------------- int main (int argc, char *argv[]) { if (argc != 3) { printf("Usage: %s <tapname> <uartdev>\n", argv[0]); printf("Example: sudo %s tap0 /dev/ttyS1\n", argv[0]); return 1; } char tapname[IFNAMSIZ]; strncpy(tapname, argv[1], IFNAMSIZ); int tap_fd = tap_alloc(tapname); int uart_fd = uart_open(argv[2]); printf("TAP interface created: %s\n", tapname); printf("UART device opened: %s\n", argv[2]); uint8_t buf[MAX_FRAME]; // Set TAP interface up (requires shell command) printf("\nRun this in another terminal:\n"); printf(" sudo ip link set %s up\n", tapname); printf(" sudo ip addr add 192.168.10.1/24 dev %s\n\n", tapname); while (1) { fd_set rfds; FD_ZERO(&rfds); FD_SET(tap_fd, &rfds); FD_SET(uart_fd, &rfds); int maxfd = (tap_fd > uart_fd ? tap_fd : uart_fd) + 1; int r = select(maxfd, &rfds, NULL, NULL, NULL); if (r < 0 && errno == EINTR) continue; if (r < 0) { perror("select"); exit(1); } // Ethernet frame from TAP → UART if (FD_ISSET(tap_fd, &rfds)) { int n = read(tap_fd, buf, MAX_FRAME); if (n > 0) { uart_send_frame(uart_fd, buf, n); } } // Frame from UART → TAP if (FD_ISSET(uart_fd, &rfds)) { int n = uart_recv_frame(uart_fd, buf, MAX_FRAME); if (n > 0) { write(tap_fd, buf, n); } } } return 0; }

How to create a virtual serial port in linux:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

# Note the output: "PTY is /dev/pts/2" and "PTY is /dev/pts/3"

How to enable NAT on a interface in Ubuntu:

Assume:

  • Outbound (WAN) interface: eth0

  • Internal/LAN interface(s): eth1, tap0, etc.

sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

Ready to go:

Then you need to define a reliable framing protocol running on UART interface that can delimit Ethernet frames.

Use two laptops and do the following test (running two program instances in one laptop and use virtual serial ports to connect each other doesn't work, the TAP interface receives frames and routes to loopback interface):

  1. Laptop A is connected to WIFI and have access to Internet, a TAP interface is also created and uses UART to simulate ethernet.

  2. Laptop B has only TAP network interface and also uses UART to transfer ethernet frames.

  3. Now, laptop A and laptop B can ping each other through UART, but laptop B can't access the WIFI domain and Internetwork.

  4. Config laptop A NAT to support traffic forwarding from TAP interface to WIFI network and finally to Internetwork.

After doing the above steps, laptop B can now successfully pinging www.baidu.com and accessing CSDN web page (though in a very slow speed):

Why doing this?

I saw the need to communicate between MCU systems and Linux systems through secure channels, either we define a protocol for key exchange or we just use TLS protocol.

So I tried this solution using UART to deliver Ethernet frames and create a virtual NIC in Linux to pass Ethernet frames to Linux TCP/IP stack and can also provide frame forwarding so as to let the MCU have access to the Internet.

For the MCU, lwIP or similar TCP/IP stack can be used for this UART based NIC, I personally have tested uIP which pings fine.

http://www.cnnetsun.cn/news/21824.html

相关文章:

  • Kubernetes备份工具API实战指南:从入门到精通
  • 18、Linux数据搜索、提取与归档全解析
  • 19、Linux 文件操作与编辑全解析
  • 日薪2000+的 “ 护网行动 ” 到底是什么?
  • 百度网盘秒传技术终极指南:零基础掌握极速文件传输
  • 2026年金融/咨询行业求职风向标:顶级简历模板权威榜单
  • 5大关键技巧彻底掌握AgentWeb:从基础配置到企业级实战
  • 轻松搞定视频下载:Seal让你的手机变身多媒体收藏库
  • FluidNC:ESP32运动控制的革命性解决方案
  • dify 导入工作流,会有些插件报错
  • 基于百度地图打造“美食地图”与3D路线规划
  • 【硬件新人指南】从零入门硬件行业:技能树、学习路径与职业规划
  • 《无人驾驶航空器飞行管理暂行条例》核心内容梳理
  • VFXToolbox:视觉特效制作终极解决方案
  • 融合空域相关法规体系深度研究
  • 揭秘!虾爬油炸机如何让效率飙升300%?
  • 学习日记day47
  • 0基础该如何转行网络安全?值得吗?
  • WebPlotDigitizer终极安装指南:从图表图像一键提取数据的完整教程
  • ModernWMS开源仓库管理系统:中小企业免费仓储解决方案快速上手指南
  • SO-ARM100开源协作机器人:从入门到精通的双臂同步控制指南
  • Obsidian个人知识管理(PKM)工具
  • CFD: NASA OVERFLOW(Overset Grid Solver for Flow Simulation)求解器
  • Apollo红外反射成像技术穿透木质屏风表面退化颜料与清漆层,破解褪色密码穿透表层窥见历史
  • 为你的STM32毕设项目加点“料”:“AI厨房安全卫士“火情监测与语音报警系统
  • heatmap.js v2.0终极迁移指南:快速升级你的热力图项目
  • 从英文困扰到建筑大师:我的Masa模组汉化蜕变之旅
  • Windows 11圆角禁用工具:一键回归经典直角窗口
  • Calamari OCR终极指南:如何快速掌握高效文字识别技术
  • 鸿蒙技术干货10:鸿蒙图形渲染基础,Canvas绘图与自定义组件实战