《TCP/IP詳解卷2:實現》筆記--選路插口

一個進程使用選路域(routing domain)中的一個插口來發送和接收選路報文,socket系統調用需要制定一個PF_ROUTE

的族類型和一個SOCK_RAW的插口類型。該進程可以向內核發送以下五種選路報文:

1.RTM_ADD:增加一條新路由。

2.RTM_DELETE:刪除一條已經存在的路由。

3.RTM_GET:取得有關一條路由的所有信息。

4.RTM_CHANGE:改變一條已經存在路由的網關、接口或者度量。

5.RTM_LOCK:說明內核不應該修改哪個變量。

本章簡介選路域、爲每個選路插口創建的選路控制塊、處理進程產生的報文的函數(route_output)、發送選路報文給一個

或多個進程的函數(raw_input)、以及不同的支持一個選路插口上所有插口操作的函數。


1.routedomain和protosw結構

下圖列出了稱爲routedomain的PF_ROUTE域的domain結構。


與支持多個協議(TCP、UDP和ICMP等)的Internet域不一樣,在選路域中只支持SOCK_RAW類型的一種協議。下圖列出

了PF_ROUTE域的協議轉換項。



2.選路控制塊

每當採用如下形式的調用創建一個選路插口時,

socket(PF_ROUTE,SOCK_RAW,protocol);

對協議的用戶請求函數(route_usrreq)的一個對應的PRU_ATTACH請求分配一個選路控制塊,並將它連接到插口結構上。

protocol參數可以將它發送給這個插口上的進程的報文類型限制爲一個特定族。例如,如果將protocol參數說明爲AF_INET,

只有包含了Internet地址的選路報文將被髮送給這個進程。

我們把這些結構稱爲選路控制塊,而不是原始控制塊(raw control block),下圖顯示了rawcb結構的定義。


另外,分配了一個相同名字的全局結構,rawcb,作爲這個雙向鏈表的頭,如下圖所示。



3.route_output函數

當給協議的用戶請求函數發送PRU_SEND請求時,就會調用route_output,這是一個進程向一個選路插口進行些操作所

引起的。函數的大概處理流程如下:



4.raw_input函數

向一個進程發送的所有選路報文----包括由內核產生的和由進程產生的----都被傳遞給raw_input,後者選擇接收這個報文的

進程。該函數的大概處理流程如下:

1.比較地址族和協議。循環遍歷每個選路控制塊來查找一個匹配。

2.比較本地的和外部的地址。這兩個測試比較了控制塊裏的本地地址和外部地址。

3.將報文添加到插口的接收緩存中。將報文的一個複製添加到那個插口的接收緩存中,並且在這個接收緩存等待的任何進程

都會被喚醒。


5.route_usrreq函數

route_usrreq是選路協議的用戶請求函數。它被不同的操作調用。函數的大概處理流程如下:

1.如果是PRU_ATTACH:分配控制塊

當進程調用socket時,就會發出PRU_ATTACH請求。爲一個選路控制塊分配內存。

2.如果是PRU_DETACH:計數器遞減

close系統調用發出PRU_DETACH請求。如果socket結構指向一個協議控制塊,route_cb結構的計數器中有兩個被減1:一個

是any_count;另一個是基於該協議的計數器。

3.處理請求。函數raw_usrreq被調用來進一步處理PRU_xxx請求。

4.計數器遞增。

5.連接插口。永久地連接到新的插口來接收PF_ROUTE族的選路報文。

6.默認情況下使能SO_USELOOPBACK。使能SO_USELOOPBACK插口選項。這是一個默認使能的插口選項。


6.raw_usrreq函數

raw_usrreq完成在選路域中用戶請求處理的大部分工作。它被route_usrreq函數所調用。用戶請求的處理被劃分成這兩個函數,

是因爲其他的一些協議調用raw_usrreq而不是route_userreq。raw_usrreq並不是想要成爲pr_usrreq函數,相反,它是一個

被不同的pr_usrreq函數調用的公共的子例程。

函數的主要對各種PRU_XXX請求進行處理:

PRU_ATTACH請求時socket系統調用的一個結果,該請求會調用raw_attach函數將控制塊連接到雙向鏈表中。

PRU_DETACH是由close系統調用發出的請求。該請求會調用raw_detach函數從雙向鏈表中刪除這個控制塊。

PRU_CONNECT2請求來自與socketpair系統調用,在路由選擇域中不被支持。

PRU_DISCONNECT請求在PRU_DETACH請求之前由close發出,因爲一個選路插口總是連接的。該請求會調用raw_disconnect釋放該插口的控制塊。

PRU_SHUTDOWN請求時shutdown系統調用發出的,該請求會調用socantsendmore函數禁止以後的寫操作。

PRU_SEND請求時sosend發出的,最終會調用pr_output函數,也就是route_output函數。

如果發出了一個PRU_ABORT請求,該控制塊被斷開連接,插口被釋放,然後斷開連接。

PRU_SENSE請求時有fstat系統調用發出的,函數返回OK。

PRU_RCVOOB,PRU_RCVD,PRU_LISTEN,PRU_ACCEPT,PRU_SENDOOB請求不被支持。

PRU_SOCKADDR和PRU_PEERADDR請求分別來自與getsockname和getpeername系統調用。前者總是返回一個錯誤,

因爲設置本地地址的bind系統調用在路由選路域中不被支持。後者總是返回插口地址結構route_src的內容,這個內容是由

route_usrreq作爲外部地址設置的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章