0731-84728105
15116127200
二層交換機原型設計(jì)與實現(xiàn)(五)
發布時(shí)間:2021-05-24
     MAC地址的學習是指使用(yòng)分組中的源MAC地址進行查表,最後添加或更新到(dào)MAC轉發表中。目的MAC查找是指使用(yòng)分組中的目的MAC進行查表,獲得該MAC在學習中保存的端口号信息。兩個過程都需要對(duì)表進行遍曆操作(zuò),根據邏輯功能(néng)的不同,其輸入輸出參數也(yě)不一樣。二層交換的核心邏輯就是這(zhè)兩個功能(néng)函數。
     1)源MAC提取
     首先,源MAC地址獲取要根據MAC層協議(yì)來(lái)解析,從(cóng)其對(duì)應的位置提取相應的數據。其次,源MAC的提取有多種方式,主要取決于對(duì)MAC地址的操作(zuò)方式,如相等比較。由于MAC地址是不規整的數據類型,通常可以使用(yòng)内存塊的比較方式或拆分成幾部分的方式比較,拆分一般可分爲2+2+2;兩種方式都要使用(yòng)指針傳遞參數。

/*分組源MAC指針獲取*/
&pkt->data[MAC_LEN]/*MAC_LEN宏定義爲6,表示MAC地址占6個字節*/
/*判斷兩個MAC地址是否相等*/
int ether_addr_equal(u8 *addr1,u8 *addr2)
{
u16 *a = (u16 *)addr1;
u16 *b = (u16 *)addr2;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
}

      2)學習過程
     前面分析過,在學習過程中并不清楚原MAC轉發表中是否存在原表項,如果先查一次是否存在,再查一次哪有空(kōng)位用(yòng)作(zuò)存儲,則需要做兩次全表遍曆。所以,針對(duì)MAC學習的處理(lǐ)方式就是不管有沒有,都當做是新增的方式處理(lǐ)。若查表不存在則存儲在一個空(kōng)白(bái)表項位置,若查表存在,則刷新端口信息。

void learn_smac(u8 inport,u8 *smac)
{
int i = 0,j = -1;
u64 zero_mac = 0;/*定義一個全零MAC地址*/
xprintf("learn_smac->\n");
for(;i<>
{
if(!ether_addr_equal(smac,obx_mac_tbl->row[i].mac))
{
/*MAC轉發表當前i行的MAC地址與輸入參數smac相等*/
if(obx_mac_tbl->row[i].port != inport)
{
/*這(zhè)個MAC地址發生了(le)端口遷移*/
}
obx_mac_tbl->row[i].port = inport;
return;/*學習過程完成,立即返回*/
}
else if(j == -1 && !ether_addr_equal((u8 *)&zero_mac,obx_mac_tbl->row[i].mac))
{
j = i;/*記錄第一個找到(dào)爲空(kōng)白(bái)表項位置*/
}
}
/*j==-1說明(míng)既沒有匹配上(shàng)MAC,也(yě)找不到(dào)空(kōng)閑位置存儲*/
if(j == -1)
{
xprintf("learn_smac->Table overflow!\n");
return;
}
/*将該MAC存儲到(dào)j的位置*/
memcpy(obx_mac_tbl->row[j].mac,smac,MAC_LEN);
obx_mac_tbl->row[j].port = inport;
xprintf("learn_smac->add new MAC,port:%d,index:%d\n",inport,j);
}

     1)目的MAC提取
     目的MAC提取與源MAC類似,在參數傳遞過程中均用(yòng)指針方式,故其表示方式爲:

/*分組目的MAC指針獲取*/
pkt->data/*數組名即爲指針*/

     2)查表過程
     查表過程就是一個簡單的全表搜索,找到(dào)的匹配的MAC地址,則返回其學習到(dào)的端口号。若是沒有找到(dào)匹配的MAC,則需要用(yòng)個特别的數字(-1)來(lái)區(qū)分正常的端口号。

int find_dmac(u8 inport,u8 *dmac)
{
int i = 0,ret = -1;/*匹配不到(dào)相同MAC,則返回-1*/
for(;i<>
{
if(obx_mac_tbl->row[i].port != inport
&& !ether_addr_equal(dmac,obx_mac_tbl->row[i].mac))
{
ret = obx_mac_tbl->row[i].port;
break;
}
}
xprintf("find_dmac->ret = %d\n",ret);
return ret;
}

     1)表的查找
     表的查找與表的設計(jì)相關,如上(shàng)我們設計(jì)的是一種簡單的數組結構,故也(yě)隻能(néng)進行順序查找的方式進行遍曆。這(zhè)種查表方式在實際應用(yòng)場景下(xià)一般不會(huì)使用(yòng),但(dàn)在設計(jì)原型系統時(shí)卻很(hěn)方便。順序查表根據表的大(dà)小(xiǎo)和(hé)使用(yòng)條數增加會(huì)導緻查表速度越來(lái)越慢,上(shàng)述在源MAC學習過程中,會(huì)順帶把空(kōng)閑位置也(yě)找出來(lái),減少一次表的遍曆。那麽查目的MAC時(shí)也(yě)需要遍曆一次表,我們是不是也(yě)可以都放(fàng)在這(zhè)一次表的遍曆中完成呢(ne)?當然是可以的,隻是這(zhè)樣實現(xiàn)對(duì)業務的邏輯理(lǐ)解沒有那麽好(hǎo),但(dàn)對(duì)表的遍曆隻需要一次即可,從(cóng)執行速度上(shàng)來(lái)說确實會(huì)提升。
     另外(wài),在對(duì)表的高(gāo)效性處理(lǐ)方面,一般不會(huì)采用(yòng)全表項匹配或多字段匹配的方法,在表設計(jì)時(shí)會(huì)使用(yòng)一個有效位字段,通過有效位的簡單比較就可确定表項是否爲空(kōng)或存在有效數據。這(zhè)種方法普遍存在于硬件邏輯設計(jì)中,硬件的查表方式也(yě)多種多樣,通常使用(yòng)基于内容可尋址存儲器(CAM)方式查表,既簡單又高(gāo)效。
     2)分組輸出
     二層交換的分組輸出主要根據查目的MAC的結果來(lái)處理(lǐ),當查詢到(dào)相應的輸出端口後,即可從(cóng)指定的端口輸出;當查不到(dào)該MAC的端口信息時(shí),則隻能(néng)通過泛洪的方式轉發,這(zhè)是在交換機層面确保數據不丢包的一種措施,甯可多發包,也(yě)不丢包。當然,廣播地址也(yě)是需要泛洪的,多播地址則需要根據其組信息進行端口組發送。下(xià)一篇文(wén)章我們來(lái)說一下(xià)分組輸出的單播和(hé)多播。
      歡迎您和(hé)學生們加入FAST開(kāi)源項目群溝通與探讨,一起體驗不一樣的系統設計(jì)過程。請(qǐng)先加微信号15116127200後邀請(qǐng)入群。

關注FAST開(kāi)源社區(qū)
FAST一一開(kāi)源、開(kāi)放(fàng)、高(gāo)速、高(gāo)效、可編程、可定義!軟硬件協同并行處理(lǐ)。