協議概述
PPPoE分為兩個階段,即Discovery(地址發現)階段和PPP會話階段。當某個主機希望發起一個PPPoE會話時,它必須首先執行Discovery來確定對方的以太網MAC地址並建立起一個PPPoE會話標識符SESSION_ID(Access Concentrator生成)。雖然PPP定義的是端到端的對等關系,Discovery卻是天生的一種客戶端-服務器關系。在Discovery的過程中,主機(作為客戶端)發現某個訪問集中器(Access Concentrator,作為服務器),根據網絡的拓撲結構,可能主機能夠跟不止一個的訪問集中器通信 。Discovery階段允許主機發現所有的訪問集中器並從中選擇一個。當Discovery階段成功完成之后,主機和訪問集中器兩者都具備了用於在以太網上建立點到點連接所需的所有信息。
Discovery階段保持無狀態(stateless)直到建立起一個PPP會話。一旦PPP會話建立,主機和訪問集中器兩者都必須為一個PPP虛擬接口分配資源。
報文格式
以太網幀格式(更多介紹請查看RFC894/tcp/ip協議詳解:卷1 第2章)
ETHER_TYPE設置為0x8863(Discovery階段)或者0x8864(PPP會話階段)
payload頭
payload內容
包含0個或多個tag,每個tag是一個tlv(type-length-value)三元組
發現階段(discovery stage)
發現階段分為四步:PADI、PADO、PADR、PADS。
當HOST收到PADS后,那么HOST與AC(access concentrator)間的點對點關系就已建立,進入了會話階段(session stage)。
PPPoE Active Discovery Initiation數據包(PADI)
主機發送DESTINATION_ADDR 為廣播地址的PADI數據包,CODE域設置為0x09,SESSION_ID域必須設置為0x0000。
PADI數據包必須包含且僅包含一個TAG_TYPE為Service-Name的TAG,以表明主機請求的服務,以及任意數目的其它類型的TAG。整個PADI數據包(包括PPPoE頭部)不允許超過1484個字節,以留足空間讓中繼代理(向數據包中)增加類型為Relay-Session-Id的TAG。
The PPPoE Active Discovery Offer 數據包(PADO)
如果訪問集中器能夠為收到的PADI請求提供服務,它將通過發送一個PADO數據包來做出應答。DESTINATION_ADDR為發送PADI的主機的單播地址,CODE域為0x07,SESSION_ID域必須設置為0x0000。
PADO數據包必須包含一個類型為AC-Name的TAG(包含了訪問集中器的名字),與PADI中相同的Service-Name,以及任意數目的類型為Service-Name的TAG表明訪問集中器提供的其它服務。如果訪問集中器不能為PADI提供服務,則不允許用PADO作響應。
The PPPoE Active Discovery Request 數據包(PADR)
由於PADI是廣播的,主機可能收到不止一個PADO,它將審查接收到的所有PADO並從中選擇一個。可以根據其中的AC-Name或PADO所提供的服務來作出選擇。然后主機向選中的訪問集中器發送一個PADR數據包。其中,DESTINATION_ADDR域設置為發送PADO的訪問集中器的單播地址,CODE域設置為0x19,SESSION_ID必須設置為0x0000。
PADR必須包含且僅包含一個TAG_TYPE為Service-Name的TAG,表明主機請求的服務,以及任意數目其他類型的TAG。
The PPPoE Active Discovery Session-confirmation 數據包(PADS)
當訪問集中器收到一個PADR數據包,它就准備開始一個PPP會話。它為PPPoE會話創建一個唯一的SESSION_ID並用一個PADS數據包來給主機作出響應。DESTINATION_ADDR域為發送PADR數據包的主機的單播以太網地址,CODE域設置為0x65,SESSION_ID必須設置為所創建好的PPPoE會話標識符。
PADS數據包包含且僅包含一個TAG_TYPE為Service-Name的TAG,表明訪問集中器已經接受的該PPPoE會話的服務類型,以及任意數目的其他類型的TAG。
如果訪問集中器不喜歡PADR中的Service-Name,那么它必須用一個帶有類型為Service-Name-Error的TAG(以及任意數目的其它TAG類型)的PADS來作出應答。這種情況下,SESSION_ID必須設置為0x0000。
The PPPoE Active Discovery Terminate數據包(PADT)
這種數據包可以在會話建立以后的任意時刻發送,表明PPPoE會話已經終止。它可以由主機或訪問集中器發送,DESTINATION_ADDR域為單播以太網地址,CODE域設置為0xa7,SESSION_ID必須表明終止的會話,這種數據包不需要任何TAG。
當收到PADT以后,就不允許再使用該會話發送PPP流量了。在發送或接收到PADT后,即使是常規的PPP結束數據包也不允許發送。PPP通信雙方應該使用PPP協議自身來結束PPPoE會話,但在無法使用PPP時可以使用PADT。
會話階段(session stage)
一旦PPPoE會話開始,PPP數據就像其它PPP封裝一樣發送。所有的以太網數據包都是單播的。ETHER_TYPE域設置為0x8864。PPPoE的CODE必須設置為0x00。PPPoE會話的SESSION_ID不允許發生改變,必須是Discovery階段所指定的值。PPPoE的payload包含一個PPP幀,幀始於PPP Protocol-ID。
TAG_TYPE和TAG_VALUE
0x0000 End-Of-List
該TAG表明表中沒有其它TAG了。該TAG的TAG_LENGTH必須總是0。不要求使用該標簽,存在是為了向后兼容。
0x0101 Service-Name
該TAG表明后面緊跟的是服務的名稱。TAG_VALUE是不以NULL結束的UTF-8字符串。當TAG_LENGTH為0時,該TAG用於表明接受任何服務。使用Service-Name標簽的例子是表明ISP(Internet服務提供商)或者一類服務或者服務的質量。
0x0102 AC-Name
該TAG表明后面緊跟的字符串唯一地表示了某個特定的訪問集中器。它可以是商標、型號以及序列號等信息的集合,或者該訪問集中器MAC地址的一個簡單的UTF-8表示。它不以NULL來結束。
0x0103 Host-Uniq
該TAG由主機用於把訪問集中器的響應(PADO或者PADS)與主機的某個唯一特定的請求聯系起來。TAG_VALUE是主機選擇的長度和值為任意的二進制數據。它不能由訪問集中器解釋。主機可以在PADI或者PADR中包含一個Host-Uniq標簽。如果訪問集中器收到了該標簽,它必須在對應的PADO或者PADS中不加改變的包含該標簽。
0x0104 AC-Cookie
該TAG由訪問集中器用於防止拒絕服務攻擊(見“安全方面的考慮”)。訪問集中器可以在PADO數據包中包含該TAG。如果主機收到了該標簽,它必須在接下來的PADR中不加改變的包含該標簽。TAG_VALUE I是長度和值任意的二進制數據,不能由主機解釋。
0x0105 Vendor-Specific
該TAG用來傳送廠商自定義的信息。TAG_VALUE的頭4個字節包含了廠商的識別碼 ,其余字節尚未定義。廠商識別碼的高字節為0,低3個字節為網絡字節序的廠商的SMI網絡管理專用企業碼,如“定義值RFC”(參考文獻[4])中定義的那樣。
不推薦使用該TAG。為了確保互操作性,實現可以悄悄的忽略Vendor-Specific TAG。
0x0110 Relay-Session-Id
該TAG可由中繼流量的中間代理加入到Discovery數據包中。TAG_VALUE對主機和訪問集中器都是晦澀難懂的(paque)。如果主機或訪問集中器收到該TAG,則它們必須在所有的Discovery數據包中包含該TAG以作為響應。所有的PADI數據包必須保證足夠空間來加入TAG_VALUE長度為12字節的Relay-Session-Id標簽。
如果Discovery數據包中已經包含一個Relay-Session-Id標簽,則不允許再加入該標簽。這種情況下,中間代理應該使用該現有的Relay-Session-Id標簽。如果它不能使用現有的標簽,或者沒有足夠空間來增加一個Relay- Session-Id標簽,那么它應該向發送者返回一個Generic-Error標簽。
0x0201 Service-Name-Error
該TAG(典型的有一個長度為零的數據部分)表明了由於某種原因,沒有理睬所請求的Service-Name。如果有數據部分,並且數據部分的頭一個字節非0,那么它必須是一個 可打印的UTF-8字符串,解釋請求被拒絕的原因。該字符串可以不以NULL結束。
0x0202 AC-System-Error
該TAG表明了訪問集中器在處理主機請求時出現了某個錯誤。(例如沒有足夠資源來創建一個虛擬電路。PADS數據包中可以包含該標簽。
如果有數據,並且數據的第一個字節不為0,那么(數據)必須是一個可打印的UTF-8 字符串,該字符串解釋了錯誤的性質。該字符串可以不以NULL結束。
0x0203 Generic-Error
該TAG表明發生了一個錯誤。當發生一個不可恢復的錯誤並且沒有其它合適的TAG時,它可被加到PADO, PADR或PADS數據包中。如果出現數據部分,那么數據必須是一個UTF-8字符串,解釋錯誤的性質。該字符串不允許以NULL結束。