0731-84728105
15116127200
二層交換機原型設計與實現(四)
發布時(shí)間:2021-05-17
     MAC轉發表是(shì)二層交換機原型中的(de)核心内容,所有的(de)數據操作都是(shì)圍繞這(zhè)張表而(ér)來(lái)。前一篇文章中講到(dào)了(le/liǎo)該表涉及的(de)兩個(gè)核心字段:端口号與MAC地(dì / de)址。本篇文章專門講解一下該MAC轉發表的(de)設計與表的(de)操作方法。
     MAC轉發表的(de)設計我們還是(shì)遵循漸進式的(de)方法,從最基本的(de)字段開始,根據需要(yào / yāo)再逐步增加。
     1)字段設計
     從前一篇文章分析,對于(yú)MAC轉發表來(lái)說(shuō),其核心字段就(jiù)2個(gè):端口号和(hé / huò)MAC地(dì / de)址,故我們對其字段的(de)設計也(yě)就(jiù)采用此二元數據。交換機的(de)端口号一般不(bù)超過64,故用char(8位)類型定義即可,MAC地(dì / de)址的(de)位寬爲(wéi / wèi)48位,可定義爲(wéi / wèi)6個(gè)字節數組。一般在(zài)協議字段中或以(yǐ)協議字段作爲(wéi / wèi)字段的(de)表結構定義中,采用無符号類型做定義,這(zhè)樣方便數據與或運算,也(yě)方便硬件移植。字段數據類型的(de)定義一般也(yě)建議重定義爲(wéi / wèi)簡寫方式,在(zài)讀寫代碼時(shí),更好理解和(hé / huò)把握數據是(shì)否溢出(chū)、越界等。

     數據類型重定義如下:

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
//typedef unsigned long u64;/*64位系統*/
/*請特别的(de)注意!!!在(zài)32位系統下,long的(de)數據位寬隻有32位,64位的(de)數據類型必須使用long long的(de)方式定義*/
typedef unsigned long long u64;/*32位系統,實驗平台OpenBox-S4爲(wéi / wèi)32位系統*/

      2)表結構設計
     數據存儲結構的(de)設計有很多方式可選,如數組、多維數組、單向鏈表、雙向鏈表和(hé / huò)樹結構等。在(zài)原型系統的(de)設計中,因爲(wéi / wèi)表結構定義會影響到(dào)整個(gè)代碼實現,且需要(yào / yāo)考慮将來(lái)硬件卸載的(de)便捷性,所以(yǐ)我們一般建議采用較爲(wéi / wèi)簡單的(de)表存儲結構。又因爲(wéi / wèi)每條表項的(de)大(dà)小是(shì)固定空間,所以(yǐ)采用數組的(de)形式是(shì)較優的(de)選擇。
     先定義一條表項的(de)數據結構如下:

struct row_port_mac
{
u8 port;
u8 pad;/*爲(wéi / wèi)了(le/liǎo)對齊做的(de)補充*/
u8 mac[MAC_LEN];
};

     補充對齊:上(shàng)述表項一條寬度爲(wéi / wèi)7個(gè)字節,如此按數組形式組織的(de)話,則會讓mac字段在(zài)非内存對齊位置出(chū)現,導緻數據比較時(shí)需要(yào / yāo)兩次對比。若是(shì)跨了(le/liǎo)CacheLine,則會導緻更長的(de)時(shí)間損耗。具體原因請網上(shàng)搜索“内存對齊”深入學習。我們建議在(zài)定義數組項的(de)時(shí)候一定按照8字節倍數對齊方式來(lái)定義,若小于(yú)8字節,則補充爲(wéi / wèi)8;若多于(yú)8,則再多補充直到(dào)成爲(wéi / wèi)8的(de)倍數(特别說(shuō)明,這(zhè)是(shì)針對數組定義要(yào / yāo)求,不(bù)同數據結構根據分析會有不(bù)同的(de)優化定義方法)。
     再定義整張表的(de)數據結構如下:

#define OBX_MAC_MAX 128/*系統最多支持128條MAC表項*/
struct table_port_mac
{
struct row_port_mac row[OBX_MAC_MAX];
};

     3)表操作方法設計
     表的(de)方法主要(yào / yāo)是(shì)指對表的(de)操作,通常包括表項的(de)增、删、改和(hé / huò)查四個(gè)動作。這(zhè)些表動作的(de)設計與表的(de)結構定義和(hé / huò)表的(de)數據操作方法相關,可以(yǐ)利用對表數據的(de)操作進行優化和(hé / huò)精簡。如在(zài)二維數據中進行任何操作,都得先把表遍曆一次,找到(dào)空位才能增加,找到(dào)對應的(de)内容項才能修改和(hé / huò)删除。
     根據二層交換的(de)數據處理流程分析,在(zài)源MAC的(de)學習過程中,學習到(dào)一個(gè)新MAC地(dì / de)址需要(yào / yāo)進行增加表項操作,若已經學習到(dào)的(de)MAC地(dì / de)址發生了(le/liǎo)端口遷移,則需要(yào / yāo)更新其端口信息。在(zài)目的(de)MAC查表過程中是(shì)一個(gè)單純的(de)MAC地(dì / de)址查找過程。MAC表項的(de)删除一般發生在(zài)MAC表老化的(de)時(shí)候,後面文章單獨講。
     結合前面的(de)表方法設計和(hé / huò)二層交換的(de)數據處理邏輯,我們暫将MAC轉發表的(de)方法定義爲(wéi / wèi)兩個(gè):一是(shì)源MAC學習;二是(shì)目的(de)MAC查找。
     1)源MAC學習
     源MAC學習是(shì)指将一個(gè)輸入分組的(de)源MAC地(dì / de)址學習并保存到(dào)MAC轉發表中。若MAC轉發表中不(bù)存在(zài)該源MAC地(dì / de)址信息,則找一個(gè)空白位置存儲。若MAC轉發表中已有該地(dì / de)址信息,則刷新(覆蓋)其端口号信息。在(zài)查找源MAC地(dì / de)址是(shì)否存在(zài)時(shí),同時(shí)查找空閑表項位置,這(zhè)樣隻用遍曆一次表,即可完成兩件事情。另外就(jiù)是(shì)查找到(dào)源MAC地(dì / de)址後,立即刷新其端口号,可以(yǐ)判斷并打印顯示,該MAC地(dì / de)址是(shì)否發生了(le/liǎo)端口轉移。
     2)目的(de)MAC查找
     目的(de)MAC的(de)查找,其目的(de)是(shì)爲(wéi / wèi)了(le/liǎo)獲得查找MAC對應的(de)端口号,查表結果有兩種情況,一是(shì)查找到(dào)了(le/liǎo),返回對應的(de)端口号信息;二是(shì)沒有查找到(dào),則不(bù)能返回正常端口數據,需要(yào / yāo)使用特殊返回值表示,如-1。
     1)查表設計
     MAC轉發表的(de)方法設計爲(wéi / wèi)什麽把二層交換的(de)功能和(hé / huò)表操作混在(zài)了(le/liǎo)一起?因爲(wéi / wèi)在(zài)二層交換中,其核心數據處理流程就(jiù)是(shì)針對MAC轉發表進行的(de)一系列數據查找、存儲和(hé / huò)更新動作。按照其邏輯處理方式來(lái)設計可以(yǐ)讓學生更好理解MAC表的(de)操作流程與細節。
     在(zài)邏輯設計的(de)過程中,我們需要(yào / yāo)針對一些特定功能進行抽象、模塊化,比如表的(de)四操作。但在(zài)具體實現過程中,其本身的(de)邏輯處理也(yě)就(jiù)是(shì)對表的(de)内容進行處理,以(yǐ)數據流程爲(wéi / wèi)主線進行設計比純模塊化的(de)分層設計更容易讓學生掌握交換的(de)處理過程。模塊化和(hé / huò)分層可以(yǐ)放到(dào)後期優化階段。
     表操作的(de)方法也(yě)并不(bù)一定要(yào / yāo)馬上(shàng)全部實現,根據邏輯的(de)需要(yào / yāo)逐個(gè)實現,在(zài)實現過程中也(yě)會不(bù)斷修改完善。
     2)MAC地(dì / de)址學習與查表實現
     MAC地(dì / de)址的(de)學習與查找是(shì)二層交換的(de)核心,特别是(shì)MAC地(dì / de)址學習,如何設計快速、高效的(de)學習方法,取決于(yú)我們對系統數據處理流程的(de)深度理解與優化叠代。下一篇文章中會給出(chū)一種具體的(de)實現方法供大(dà)家參考。
      歡迎您和(hé / huò)學生們加入FAST開源項目群溝通與探讨,一起體驗不(bù)一樣的(de)系統設計過程。請先加微信号15116127200後邀請入群。

關注FAST開源社區
FAST一一開源、開放、高速、高效、可編程、可定義!軟硬件協同并行處理。