news 2026/7/10 18:15:07

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/7/6 8:32:49

Kubernetes备份工具API实战指南:从入门到精通

为什么需要API驱动的备份解决方案 【免费下载链接】velero Backup and migrate Kubernetes applications and their persistent volumes 项目地址: https://gitcode.com/GitHub_Trending/ve/velero 在现代云原生环境中&#xff0c;Kubernetes集群的备份和恢复已从手动操…

作者头像 李华
网站建设 2026/7/9 17:50:32

18、Linux数据搜索、提取与归档全解析

Linux数据搜索、提取与归档全解析 在日常使用Linux系统时,我们经常会涉及到数据的搜索、提取以及归档等操作。掌握这些操作的技巧和工具,能够显著提高我们的工作效率。下面将详细介绍这些操作的相关内容。 1. 统计文本文件信息 wc 命令是一个非常实用的工具,它可以用于统…

作者头像 李华
网站建设 2026/7/6 1:29:00

19、Linux 文件操作与编辑全解析

Linux 文件操作与编辑全解析 1. 文件搜索、提取与归档基础 在 Linux 系统中,文件管理常常涉及到文件的定位、提取和归档等操作。 grep 和 find 工具在文件定位方面发挥着重要作用。 grep 利用正则表达式来查找文件中匹配特定模式的内容,通过重定向操作符,还能将其他…

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

日薪2000+的 “ 护网行动 ” 到底是什么?

中国“护网”行动&#xff1a;构筑国家网络空间的钢铁长城 在数字化浪潮席卷全球的今天&#xff0c;网络安全已成为国家安全的核心支柱。为应对日益严峻的网络安全威胁&#xff0c;中国自2016年起开展了一项规模宏大、影响深远的国家级网络安全行动——“护网行动”。这场由政…

作者头像 李华
网站建设 2026/7/9 1:14:49

百度网盘秒传技术终极指南:零基础掌握极速文件传输

百度网盘秒传技术终极指南&#xff1a;零基础掌握极速文件传输 【免费下载链接】baidupan-rapidupload 百度网盘秒传链接转存/生成/转换 网页工具 (全平台可用) 项目地址: https://gitcode.com/gh_mirrors/bai/baidupan-rapidupload 还在为文件传输缓慢而烦恼&#xff1…

作者头像 李华
网站建设 2026/7/10 11:27:58

2026年金融/咨询行业求职风向标:顶级简历模板权威榜单

2026年的就业市场&#xff0c;特别是高精尖的金融和咨询行业&#xff0c;竞争已进入白热化阶段。对于渴望入行的金融新秀&#xff0c;或是致力于成为顶级战略顾问的精英人才而言&#xff0c;一份仅仅“合格”的简历已远远不够。它必须是精准定制、专业严谨且能瞬间抓住眼球的“…

作者头像 李华