news 2026/4/3 21:55: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/3 5:53:38

光储设计一体化,鹧鸪云让新能源项目更省心

在光储项目建设中&#xff0c;设计割裂、配储盲目、收益模糊等痛点常让从业者头疼。鹧鸪云光储仿真设计软件以“光储一体化”为核心&#xff0c;覆盖从项目选型到报告输出的全流程&#xff0c;用精准算法与智能功能破解行业难题&#xff0c;让每一个新能源项目都扎根于科学设计…

作者头像 李华
网站建设 2026/4/3 19:47:35

Docker:安装 OpenSearch 全文检索的技术指南

🚀 1、简述 OpenSearch 是一个基于 Elasticsearch 7.10.2 和 Kibana 7.10.2 分支的开源搜索与分析引擎,由 AWS 牵头维护。它兼具分布式搜索、日志分析、可视化(OpenSearch Dashboards)等能力,常用于日志平台、数据分析平台与搜索服务。 本文将介绍如何通过 Docker 快速…

作者头像 李华
网站建设 2026/4/2 11:01:03

5个理由让你爱上TypeScript语言服务器:智能编程新体验

5个理由让你爱上TypeScript语言服务器&#xff1a;智能编程新体验 【免费下载链接】typescript-language-server TypeScript & JavaScript Language Server 项目地址: https://gitcode.com/gh_mirrors/typ/typescript-language-server TypeScript语言服务器是一个遵…

作者头像 李华
网站建设 2026/4/2 14:01:32

QT软件开发知识点流程及记事本开发

1.界面设计我们通过选用基本的控件来设计出下面的ui界面&#xff1a;当然我们的效果还要有选项中的图形显示&#xff0c;如下图所示&#xff1a;这里的图标我们可以通过阿里巴巴图标库获取&#xff0c;然后将其添加到我们的资源文件中即可&#xff0c;因为对于软件图标只能使用…

作者头像 李华
网站建设 2026/4/1 7:58:44

ModernWMS仓库管理系统:从零开始的完整使用指南

想要为你的企业找到一款功能强大又完全免费的仓库管理解决方案吗&#xff1f;ModernWMS正是你需要的选择&#xff01;这个现代化的开源系统专为中小企业设计&#xff0c;提供了从收货到发货的全流程管理能力。今天&#xff0c;我将带你从零开始&#xff0c;一步步掌握这个系统的…

作者头像 李华
网站建设 2026/3/29 18:17:21

云计算技术在企业数字化转型中的应用与实践

一、云计算在企业数字化转型中的核心作用随着数字经济时代的到来&#xff0c;企业数字化转型已成为提升竞争力的关键路径。云计算作为数字化转型的技术基石&#xff0c;正在重塑企业的IT架构和业务模式。从基础设施即服务(IaaS)到软件即服务(SaaS)&#xff0c;云计算为企业提供…

作者头像 李华