PPP資料幀的編碼與解碼

來源:互聯網
上載者:User

一、摘要 

PPP協議是在ATM網路裡常用的鏈路協議,基於PPP協議的PPPoA,PPPoE在xDSL數據機中不可或缺。本文簡單描述PPP協議的幀封裝格式,並給出了一個簡單的PPP編碼與解碼演算法,以期望能對需要者有所協助。 

二、PPP協議簡介

PPP資料幀的格式看上去很像ISO的HDLC(高層資料連結控制)標準。是PPP資料
幀的格式。

每一幀都以標誌字元0x7e開始和結束。緊接著是一個地址位元組,值始終是0xff,然後是一
個值為0x03的控制位元組。

接下來是協議欄位,類似於乙太網路中類型欄位的功能。當它的值為0x0021時,表示資訊
欄位是一個IP資料報;值為0xc021時,表示資訊欄位是鏈路控制資料;值為0x8021時,表示
資訊欄位是網路控制資料。

CRC欄位(或FCS,幀檢驗序列)是一個循環冗餘檢查碼,以檢測資料幀中的錯誤。
由於標誌字元的值是0x7e,因此當該字元出現在資訊欄位中時, PPP需要對它進行轉義。
在同步鏈路中,該過程是通過一種稱作位元填充(bit stuffing )的硬體技術來完成的[ Tanenbaum
1989 ]。在非同步鏈路中,特殊字元0x7d用作逸出字元。當它出現在PPP資料幀中時,那麼緊接
著的字元的第6個位元要取其補碼,具體實現過程如下:

    1) 當遇到字元0x7e時,需連續傳送兩個字元: 0x7d和0x5e,以實現標誌字元的轉義。
    2) 當遇到逸出字元0x7d時,需連續傳送兩個字元: 0x7d和0x5d,以實現逸出字元的轉義。
    3 ) 預設情況下,如果字元的值小於0x20(比如,一個ASCII控制字元),一般都要進行轉
義。例如,遇到字元0x01時需連續傳送0x7d和0x21兩個字元(這時,第6個位元取補碼後變為
1,而前面兩種情況均把它變為0)。

這樣做的原因是防止它們出現在雙方主機的串列介面驅動程式或數據機中,因為有
時它們會把這些控制字元解釋成特殊的含義。另一種可能是用鏈路控制協議來指定是否需要
對這32個字元中的某一些值進行轉義。預設情況下是對所有的32個字元都進行轉義。

--摘自《TCP/IP詳解》卷1·協議 (W. Richard Stevens)

三、編碼與解碼

1。編碼

編碼就是按照前面所說的對需要轉義的字元進行變換,下面是簡單的實現代碼:

    001 #define PPP_FRAME_FLAG  0x7e /* 標誌字元 */

    002 #define PPP_FRAME_ESC   0x7d /* 逸出字元 */

    003 #define PPP_FRAME_ENC   0x20 /* 編碼字元 */

    004 #define BUF_LEN 1500

    005 /* return: bytes encoded */

    006 int pppEncode(unsigned char * buf, int len) {
    007  unsigned char * pi, * po;
    008  int i, olen;
    009  unsigned char obuf[BUF_LEN];

    010  if(len > (BUF_LEN>>1)) {
    011   return -1;
    012  }

    013  memset(obuf, 0, BUF_LEN);
    014  pi = buf;
    015  po = obuf;
    016  olen = len;

    017  for(i=0; i<len; i++) {

    018   /* byte needs encode, encode it */
    019   if(*pi == PPP_FRAME_FLAG
    020   || *pi == PPP_FRAME_ESC
    021   || *pi < 0x20) {
    022   *po = PPP_FRAME_ESC;
    023    po++;
    024    olen++;

    025    /* xor the 6th bit */
    026    *po = *pi ^ PPP_FRAME_ENC;
    027   }
    028   else {
    029    *po = *pi;
    030   }
    031   pi++;
    032   po++;
    033  }

    034   memcpy(buf, obuf, olen);
     
    035   return olen;
    036 }

001~003: 定義標誌字元,逸出字元和編碼字元。

010~012: 檢查要編碼的字元長度,按最壞情況,一個字元會編碼成兩個字元,所以這裡只能編碼最大緩衝區長度一半。

018~027: 編碼的主要實現,遇到標誌字元,逸出字元和小於0x20的控制字元,都要進行編碼。方法就是在其前面插入一個逸出字元0x7d,然後對其第6位取補碼。

028~030: 其他字元,不做任何修改。

034~035: 修改緩衝區,返回編碼後的字元長度。

2。 解碼

解碼實際上就是編碼的逆運算,它除去逸出字元,並對逸出字元之後的字元的第6位去補碼。

001 /* return: bytes decoded */

002 int pppDecode(unsigned char * buf, int len) {
003  unsigned char * pi, *po;
004  int i, olen;
005  unsigned char obuf[BUF_LEN];

006  if(len > BUF_LEN) {
007   return -1;
008  }

009  memset(obuf, 0, BUF_LEN);
010  pi = buf;
011  po = obuf;
012  olen = len;

013  for(i=0; i<len; i++) {
014   if(*pi == PPP_FRAME_ESC) {

015    /* skip the escape byte */
016    pi++;
017    olen--;

018    /* xor the 6th bit */
019    *po = *pi ^ PPP_FRAME_ENC;
020   }
021   else {
022    *po = *pi;
023   }
024   pi++;
025   po++;
026  }

027  memcpy(buf, obuf, olen);

028  return olen;
029 }

006~008: 檢查要解碼的字元長度。

014~020: 解碼的主要實現,遇到逸出字元,將其跳過,對緊接其後的字元的第6位去補碼。

021~023: 其他字元,不做處理。

027~028: 修改緩衝區,返回解碼後的字元長度。

此編解碼代碼以易讀為主,需要者可自行最佳化。 

---------------

僅供學習和交流,轉載請註明作者及出處,謝謝!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.