news 2026/4/15 15:58:58

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/4/5 11:16:00

第50集科立分板机:科立分板机的精度和效率如何

科立分板机在精度和效率方面表现卓越&#xff0c;具体表现如下&#xff1a;一、精度表现1、核心精度指标&#xff1a;切割精度&#xff1a;定位/重复精度通常在0.02mm至0.05mm以内&#xff0c;高端型号(如KL-3500系列)可达0.02mm&#xff0c;满足高精度切割需求。切口质量&…

作者头像 李华
网站建设 2026/4/15 20:22:06

2026年网安最新风口,网安人不能不懂!(小白必看)

总有人说网安早已从风口跌落&#xff0c;企业频繁裁员、赤字&#xff0c;现在入行压根找不到工作。 实际上&#xff0c;招聘网站上仍有大批大批的招聘信息&#xff1a; 就连央视报道&#xff0c;根据最新《AI时代网络安全产业人才发展报告&#xff08;2025&#xff09;》&…

作者头像 李华
网站建设 2026/4/15 10:30:55

粒子群优化实战指南:5个步骤从理论到工程应用

粒子群优化实战指南&#xff1a;5个步骤从理论到工程应用 【免费下载链接】pyswarms A research toolkit for particle swarm optimization in Python 项目地址: https://gitcode.com/gh_mirrors/py/pyswarms 粒子群优化&#xff08;PSO&#xff09;作为群体智能算法的…

作者头像 李华
网站建设 2026/4/16 12:49:16

终极iPhone内联视频播放指南:告别全屏困扰的完整教程

在移动端网页开发中&#xff0c;你是否曾为iPhone上的视频播放问题而烦恼&#xff1f;当你精心设计的网页视频在iOS设备上播放时&#xff0c;总是自动跳转到全屏模式&#xff0c;破坏了用户体验的连贯性。这就是iPhone内联视频播放技术要解决的核心痛点。 【免费下载链接】ipho…

作者头像 李华
网站建设 2026/4/12 13:45:54

Spring的Bean

目录 1.概念 2.Xml中Bean标签的解释 (1)id属性 (2)class属性 (3)scope 属性 (4)生命周期方法配置 3.创建Bean的三种方式 默认使用无参数的构造方法 静态工厂实例化方式 动态工厂实例化方式 factory-method&#xff1a; factory-bean&#xff1a; 1.概念 在 Spring …

作者头像 李华
网站建设 2026/4/16 12:49:50

P2构型插电式混合动力汽车:ECMS等效燃油消耗最小能量管理策略模型

P2 PEHV&#xff0c;P2构型插电式混合动力汽车ECMS等效燃油消耗最小能量管理策略 模型全部为自己手动搭建&#xff0c;参考可靠文献&#xff0c;非download随便改改糊弄&#xff0c;真正做到看的懂。 P2并联PEHV的ECMS能量管理策略。 图1是模型整体结构 图2是发动机&#xff0c…

作者头像 李华