[導讀]這篇文章主要是講解level-ip如何實現虛擬網卡接口封裝,源碼級解析!
閱讀本文需要對level-ip的整體架構有所了解,如果讀者尚未接觸過level-ip,請先閱讀下文:
分享一款Linux平臺下的tcp協(xié)議棧!超級透徹!
請根據上述文章中的指引獲取leve-ip的全部源碼,并且嘗試在任意Linux發(fā)行版本上編譯運行。
前言
在整個tcp/ip協(xié)議棧中,對協(xié)議是進行上下分層的。用戶需要收發(fā)的數據在不同協(xié)議層中傳輸時,會添加和刪除各種協(xié)議包頭。如下圖:我們暫且先把tcp協(xié)議棧粗淺地理解為:為用戶數據添加各種包頭,然后發(fā)送出去。等接收到數據之后,又按相反的順序,解析出數據包中的有效數據,然后傳輸給用戶程序。
既然數據是層層遞交的,那么我們就應該先設計好每一層協(xié)議所需要使用到的接口。這一章,我們就來分析最底層的虛擬網卡接口。這個虛擬網卡接口,以后就負責幫助我們跟互聯網進行數據收發(fā)。
虛擬網卡接口封裝
在前面的文章中,我們已經講解了虛擬網卡的基本原理,明白虛擬網卡在Linux系統(tǒng)下的設備文件為"/dev/net/tun"。下面我們來分析源碼,看如何對虛擬網卡的設備文件接口進行封裝,以方便我們日后收發(fā)數據。
打開虛擬網卡設備文件
學習過Linux系統(tǒng)編程的小伙伴應該知道,Linux下有"一切皆文件"的哲學思想,我們想要使用虛擬網卡,就應該先用open函數打開虛擬網卡文件,獲取它的文件描述符之后,然后才能對它進行讀寫等操作。在level-ip\src\tuntap_if.c文件中,有一個tun_init()函數。該函數在main()函數中被調用,負責初始化虛擬網卡設備。如下圖:
我們在這里主要是關注其中的tun_calloc()函數,在這個函數里面,就打開了"/dev/net/tun"設備文件,如下圖:
設置虛擬網卡屬性
我們的虛擬網卡,有很多不同屬性,在這里我們要去配置虛擬網卡為tap網卡,該類型網卡可以抓取以太網層數據包。配置過程也是tun_calloc()函數中完成的。如下圖:其中,配置屬性如下:
- IFF_TUN: 創(chuàng)建一個點對點設備
- IFF_TAP: 創(chuàng)建一個以太網設備
- IFF_NO_PI: 不包含包信息,默認的每個數據包當傳到用戶空間時,都將包含一個附加的包頭來保存包信息
封裝虛擬網卡讀取接口--tun_read
tun_read()其實就是對read()函數的簡單封裝,此處封裝的意義,是用來唯一標識出虛擬網卡數據讀取接口。如下圖:封裝虛擬網卡發(fā)送接口--tun_write
tun_write其實就是對write()函數的簡單封裝,此處封裝的意義,是用來唯一標識出虛擬網卡數據發(fā)送接口。如下圖:總結
到這里,我們就完成了虛擬網卡讀寫接口的封裝,這是我們萬里長征的第一步,也是最重要的一步。從上面tcp協(xié)議棧的層次圖可以看出來,它是實現以太網協(xié)議的關鍵依賴接口,以后我們將會基于這些接口,封裝出以太網協(xié)議上的數據收發(fā)接口。





