網(wǎng)絡(luò)協(xié)議——TCP/IP協(xié)議
簡(jiǎn)介:
TCP(傳輸控制協(xié)議)和 IP(網(wǎng)際協(xié)議)是兩個(gè)獨(dú)立且緊密結(jié)合的協(xié)議,負(fù)責(zé)管理和引導(dǎo)數(shù)據(jù)報(bào)文在 Internet上的傳輸。二者使用專門的報(bào)文頭定義每個(gè)報(bào)文的內(nèi)容。TCP 負(fù)責(zé)和遠(yuǎn)程主機(jī)的連接,IP負(fù)責(zé)尋址,使報(bào)文被送到其該去的地方。
TCP/IP協(xié)議模型如下圖所示:
1.網(wǎng)絡(luò)接口層
有時(shí)也稱為數(shù)據(jù)鏈路層或網(wǎng)絡(luò)接口層,通常包括操作系統(tǒng)中的設(shè)備驅(qū)動(dòng)程序和計(jì)算機(jī)中對(duì)應(yīng)的網(wǎng)絡(luò)接口卡。它們一起處理與電纜(或其他任何傳輸媒介)的物理接口細(xì)節(jié)。
2.網(wǎng)絡(luò)層
有時(shí)也稱為互聯(lián)網(wǎng)層,處理分組在網(wǎng)絡(luò)中的活動(dòng),例如分組的選路。在T C P / I P協(xié)議族中,網(wǎng)絡(luò)層協(xié)議包括I P協(xié)議(網(wǎng)際協(xié)議),I C M P協(xié)議(I n t e r n e t互聯(lián)網(wǎng)控制報(bào)文協(xié)議),以及I G M P協(xié)議(I n t e r n e t組管理協(xié)議)。
3.傳輸層
主要為兩臺(tái)主機(jī)上的應(yīng)用程序提供端到端的通信。在 TCP/I P協(xié)議族中,有兩個(gè)互不相同的傳輸協(xié)議:TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報(bào)協(xié)議)
TCP為兩臺(tái)主機(jī)提供高可靠性的數(shù)據(jù)通信。它所做的工作包括把應(yīng)用程序交給它的數(shù)據(jù)分成合適的小塊交給下面的網(wǎng)絡(luò)層,確認(rèn)接收到的分組,設(shè)置發(fā)送最后確認(rèn)分組的超時(shí)時(shí)鐘等。由于傳輸層提供了高可靠性的端到端的通信,因此應(yīng)用層可以忽略所有這些細(xì)節(jié)。
UDP為應(yīng)用層提供一種非常簡(jiǎn)單的服務(wù)。它只是把稱為數(shù)據(jù)報(bào)的分組從一臺(tái)主機(jī)發(fā)送到另一臺(tái)主機(jī),但并不保證該數(shù)據(jù)報(bào)能到達(dá)另一端。任何必需的可靠性必須由應(yīng)用層來提供。
4.應(yīng)用層
負(fù)責(zé)處理特定的應(yīng)用程序細(xì)節(jié)
幾乎各種不同的 T C P / I P實(shí)現(xiàn)都會(huì)提供下面這些通用的應(yīng)用程序:
Telnet 遠(yuǎn)程登錄。
FTP 文件傳輸協(xié)議。
SMTP 簡(jiǎn)單郵件傳送協(xié)議。
SNMP 簡(jiǎn)單網(wǎng)絡(luò)管理協(xié)議。
5.各層主要協(xié)議
6. OSI 模型和 TCP/IP 模型的區(qū)別
6.1類似之處
均為層次結(jié)構(gòu)
存在可比的傳輸層和網(wǎng)絡(luò)層
均有應(yīng)用層,但其所提供的服務(wù)有所不同
均是一種基于協(xié)議數(shù)據(jù)單元的包交換網(wǎng)絡(luò)
作為概念上的模型和事實(shí)上的標(biāo)準(zhǔn),具有同等的重要性
6.2不同之處
OSI 模型包括了 7 層,而 TCP/IP 模型只有 4 層。TCP/IP 模型將表示層與會(huì)話層包含到了應(yīng)用層中去完成。另外,TCP/IP模型還將 OSI的數(shù)據(jù)鏈路層和物理層包括到了一個(gè)網(wǎng)絡(luò)接口層中。
OSI 參考模型在網(wǎng)絡(luò)層支持無連接和面向連接的兩種服務(wù),而在傳輸層僅支持面向連接的服務(wù)。TCP/IP 模型在網(wǎng)絡(luò)層則只支持無連接的一種服務(wù),但在傳輸層支持面向連接和無連接兩種服務(wù)。
TCP/IP由于有較少的層次,更為簡(jiǎn)單
協(xié)議棧結(jié)構(gòu)的說明
1、 驅(qū)動(dòng)中,使用ISR/POLL/NAPI等方式從硬件收包
2、 收包接口中通過netif_receive_skb()上交協(xié)議棧
3、 在netif_receive_skb()函數(shù)中做協(xié)議解析
core/dev.c中,為報(bào)文處理的第二層,用于分離收到的以太網(wǎng)報(bào)文的協(xié)議類型,同我們某產(chǎn)品上一個(gè)叫做Packet Handler模塊一樣,逐級(jí)分發(fā)報(bào)文。
該模塊有一個(gè)list_head鏈表,鏈表上掛了很多packet_type數(shù)據(jù)結(jié)構(gòu),packet_type數(shù)據(jù)結(jié)構(gòu)中包括ether_type, dev指針以及func指針等成員。
為加快對(duì)報(bào)文的分發(fā)速度,這個(gè)鏈表實(shí)現(xiàn)成了一個(gè)HASH表,共16way,使用ethertype作為索引。
內(nèi)核中常注冊(cè)的ethertype類型:
ETH_P_IP
ETH_P_ARP
ETH_P_HDLC
ETH_P_DEC
ETH_P_PPP
PKT_TYPE_LACPDU
ETH_P_PPP_SES
ETH_P_PPP_DISC
ETH_P_BPQ
ETH_P_PARP
ETH_P_802_2
ETH_P_TR_802_2
ETH_P_X25
ETH_P_8021Q
ETH_P_ALL用于所有
其中Func是上層協(xié)議的鉤子函數(shù),常用的有ip_rcv()和arp_rcv()等,然后iprcv()中又會(huì)解析ip上的協(xié)議,調(diào)用icmp_rcv/igmp_rcv/udp_rcv/tcp_rcv()等等。
新的協(xié)議類型可以在驅(qū)動(dòng)模塊加載時(shí),通過下面的接口增加到packet_type_list中:
void dev_add_pack()用于增加一種協(xié)議類型,將其packet_type指針加到鏈表上。
void dev_remove_pack()用于從list_head上刪除一種協(xié)議類型
4、 解析完報(bào)文協(xié)議之后,將報(bào)文放到skb_queue隊(duì)列中
skb_queue為系統(tǒng)底層與應(yīng)用程序之間一個(gè)接口。所有接收到的同類報(bào)文都會(huì)被掛到這個(gè)隊(duì)列上,然后由協(xié)議棧上層接口來取。
5、 協(xié)議上層接口通過系統(tǒng)調(diào)用獲取skb。代碼位于net模塊下:
sys_recv()
sys_recvfrom()
sock_recvmsg()
__sock_recvmsg()
udp_recvmsg()或者tcp_recvmsg()
__skb_recv_datagram()
ip_cmsg_recv()
從skb接收隊(duì)列skb_queue收包
某項(xiàng)目中的代碼
1. 驅(qū)動(dòng)driver使用NAPI方式,從硬件queue中收包
2. 調(diào)用netif_receiv_skb()函數(shù),上交收到的報(bào)文
這個(gè)項(xiàng)目支持NAPT,因此會(huì)在該函數(shù)中直接調(diào)用NAPT回調(diào)做NAT,而對(duì)于非NAPT印射的報(bào)文,進(jìn)行如下處理:
先遍歷ptype_all鏈表,list_for_each_entry_rcu(),最終調(diào)用packet_type.func()
編譯內(nèi)核時(shí)選上BRIDGE,則會(huì)執(zhí)行網(wǎng)橋模塊br_handle_frame_hook(skb),源文件為bridge/br.c
網(wǎng)橋模塊的初始化pkt_type為PACKET_HOST或者PACKET_OTHERHOST
如果編譯內(nèi)核時(shí)選上了mac_VLAN模塊,則會(huì)執(zhí)行macvlan_handle_frame_hook
初始化為PACKET_BROADCAST、PACKET_MULTICAST、PACKET_HOST
最后一步,判斷type==skb->protocol,會(huì)查詢鏈表,找到匹配的protocol鉤子并且調(diào)用。
3. Skb的釋放時(shí)機(jī)
如果是合法報(bào)文,放入接收隊(duì)列,在用戶系統(tǒng)調(diào)用取包時(shí)釋放,否則在netif_receiv_skb()函數(shù)中釋放。
802.1q協(xié)議模塊實(shí)現(xiàn)
帶802.1qTAG的模塊有自己?jiǎn)为?dú)的協(xié)議類型,一般是0x8100。使用前面說的packet_list操作接口注冊(cè)一個(gè)新的packet_type掛到鏈表中,這樣,所有帶TAG的報(bào)文會(huì)被轉(zhuǎn)發(fā)到802.1q的接口上。
應(yīng)用程序里,每調(diào)用vconfig創(chuàng)建一個(gè)VLAN,就會(huì)創(chuàng)建一個(gè)新的net device,這個(gè)虛擬擴(kuò)展的net device會(huì)在原來物理的net device上面工作,將VLAN對(duì)應(yīng)的報(bào)文都轉(zhuǎn)移到虛擬net device的收發(fā)接口上。
new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,vlan_setup);






