一、tun/tap概述
tun/tap是一種虛擬網絡設備,它可以將數據包從用戶空間傳輸到內核空間,或者反過來,通過用戶空間的程序來協議地訪問網絡設備。
tun/tap模塊的出現,主要是為了滿足虛擬網絡設備的需求。尤其是虛擬機技術的普及,使得網絡設備需要能夠高效地和虛擬機進行通信和交互,tun/tap成為了這方面的最佳選擇。
// 用戶空間程序創建並使用一個tun設備 #include #include #include #include #include #include int tun_alloc(char *dev) { struct ifreq ifr; int fd, err; if ((fd = open("/dev/net/tun", O_RDWR)) < 0) { return fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN; if (*dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) 0) { printf("Received %lu bytes\n", strlen(buffer)); } close(tun_fd); return 0; }
二、tun/tap的工作原理
tun/tap依賴於內核的TUN/TAP驅動模塊,它通過創建一個虛擬網絡設備,來實現一個虛擬的網絡接口,作為網絡數據包的收發通道。整個過程可以分為以下幾個步驟:
- 用戶程序申請創建tun/tap設備
- 內核向用戶程序返回tun/tap設備信息
- 用戶程序配置tun/tap設備
- tun/tap設備準備就緒,可以開始數據包的收發
- 用戶程序通過read/write等系統調用,向tun/tap設備中寫入/讀取數據包
在數據包的收發過程中,用戶程序和TUN/TAP驅動模塊之間通過ioctl系統調用交互,完成接口狀態、MAC和IP地址等的設置、讀取和修改等。同時,內核還會調度進程,執行網絡協議棧,完成數據包的處理和轉發等操作。
三、tun/tap的使用場景
tun/tap最常見的使用場景是虛擬機和容器技術,因為它可以實現網絡設備的隔離、共享和管理。在虛擬機中,將tun/tap設備掛載到虛擬機中,就可以實現虛擬機網絡設備和宿主機網絡設備之間的通信,也可以方便地實現虛擬機之間的網絡互通。
tun/tap還可以用於VPN和隧道網絡等場景,可以實現在公共網絡中建立私有網絡的功能。此外,tun/tap還可以用於網絡監控和測試等需求,方便收集和分析數據包。
四、tun/tap的高級特性
1. 多隊列支持
在網絡設備高負載的情況下,多隊列支持可以提高網絡設備的轉發性能。tun/tap對於多隊列的支持,可以通過參數設置和ioctl系統調用相結合的方式實現。通過設置多個隊列,不同流量可以被映射到不同隊列中,在每個隊列上進行處理,從而提高並發性和負載均衡性。
// 多隊列的創建與設置 int tun_queue[tun_queues]; for (int i = 0; i < tun_queues; i++) { // 創建tun設備 tun_queue[i] = tun_create(tun_queue_name[i], IFF_TAP | IFF_NO_PI); // 為tun設備設置隊列數量 ioctl(tun_queue[i], TUNSETQUEUE, i); } // 讀取隊列數據包操作 char buf[BUFLEN]; for (;;) { int ret = select(maxfd + 1, &rfds, NULL, NULL, NULL); if (ret < 0) { perror("select"); break; } for (int i = 0; i < tun_queues; i++) { // 測試該文件描述符是否就緒 if (FD_ISSET(tun_queue[i], &rfds)) { // 讀取數據 int len = read(tun_queue[i], buf, BUFLEN); if (len < 0) { perror("read()"); break; } // 處理數據包 // ... } } }
2. 用戶空間和內核空間之間的零拷貝技術
在tun/tap的數據收發過程中,往往會涉及到數據的拷貝,因為數據需要在用戶程序和內核之間進行傳遞。為了避免頻繁的數據拷貝對系統性能帶來的負面影響,tun/tap可以使用零拷貝技術,即在發送數據包時,將數據包的內存映射到內核空間,這樣就可以直接從內存中訪問數據包,避免了數據的複製操作。
int tun_fd; char buffer[2048]; tun_fd = open("/dev/net/tun", O_RDWR); if (tun_fd < 0) { perror("open"); return EXIT_FAILURE; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TUN | IFF_NO_PI; if (dev && *dev) { strncpy(ifr.ifr_name, dev, IFNAMSIZ); } if (ioctl(tun_fd, TUNSETIFF, (void *)&ifr) cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_TOS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); *(int *)CMSG_DATA(cmsg) = IPTOS_LOWDELAY; // 零拷貝技術的實現 int bytes_sent = sendmsg(tun_fd, &msg, MSG_DONTWAIT);
3. tun/tap虛擬設備的擴展
在tun/tap虛擬設備的使用中,還可以根據需要來自定義設備的協議和實現方式。比如,可以通過對TUN/TAP驅動模塊的修改,增加虛擬設備的類型和功能,也可以通過對用戶程序的修改,增加自定義的數據包處理邏輯。
原創文章,作者:TTANJ,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/333793.html