news 2026/6/10 12:55:14

Ethernet over UART

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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.

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 11:21:17

纠结!项目经理考PMP®还是CSPM,哪个更有前途?

在项目管理领域&#xff0c;证书不仅是专业能力的背书&#xff0c;更是职业发展的“通行证”。如今&#xff0c;CSPM与PMP是项目管理领域内的热门证书&#xff0c;很多项目经理在选证书时都陷入纠结&#xff1a;到底该考CSPM还是PMP&#xff1f;哪个证书更能助力长远发展&#…

作者头像 李华
网站建设 2026/6/9 19:17:31

职场上,领导不怕刺头搞事,就怕老实人突然开窍

很多人认为&#xff0c;最让领导头痛的&#xff0c;是那些不服管的刺头&#xff0c;其实并非如此&#xff0c;对于刺头&#xff0c;领导只要睁一只眼&#xff0c;闭一只眼&#xff0c;不理会刺头的无理取闹&#xff0c;也能相安无事。 而在现实中&#xff0c;大多数领导并不怕…

作者头像 李华
网站建设 2026/6/10 11:21:17

告别格式烦恼:这款神器让飞书文档秒变Markdown

告别格式烦恼&#xff1a;这款神器让飞书文档秒变Markdown 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 还在为飞书文档的格式转换而头疼吗&#xff1f;每天面对大量…

作者头像 李华
网站建设 2026/6/9 18:34:17

Screenbox媒体播放器:Windows平台终极免费视频播放解决方案

Screenbox媒体播放器&#xff1a;Windows平台终极免费视频播放解决方案 【免费下载链接】Screenbox LibVLC-based media player for the Universal Windows Platform 项目地址: https://gitcode.com/gh_mirrors/sc/Screenbox 想要一款真正懂你的免费媒体播放器吗&#x…

作者头像 李华
网站建设 2026/6/5 10:13:18

AntiDupl.NET:智能图片去重工具的完整使用指南

AntiDupl.NET&#xff1a;智能图片去重工具的完整使用指南 【免费下载链接】AntiDupl A program to search similar and defect pictures on the disk 项目地址: https://gitcode.com/gh_mirrors/an/AntiDupl 在数字时代&#xff0c;图片文件的管理已成为日常生活中的重…

作者头像 李华
网站建设 2026/6/10 11:20:06

如何在macOS上优雅展示键盘输入?终极KeyCastr可视化工具指南

如何在macOS上优雅展示键盘输入&#xff1f;终极KeyCastr可视化工具指南 【免费下载链接】keycastr KeyCastr, an open-source keystroke visualizer 项目地址: https://gitcode.com/gh_mirrors/ke/keycastr 你是否在录制屏幕演示时苦恼于观众无法看清你的快捷键操作&am…

作者头像 李华