0731-84728105
15116127200
二層交換機原型設計(jì)與實現(xiàn)(三)
發布時(shí)間:2021-05-10
     二層交換機的主要功能(néng)就是在端口之間搬移分組,當然是要根據正确的目标地址來(lái)搬移,涉及到(dào)以太網幀格式的解析、源和(hé)目的MAC地址的提取,MAC表的設計(jì)、查找和(hé)老(lǎo)化等等一系列的系統功能(néng)實現(xiàn)。我們開(kāi)始設計(jì)交換機并不考慮那麽多,從(cóng)簡單入手,輕裝上(shàng)陣,你(nǐ)也(yě)許會(huì)走得更好(hǎo)。
     上(shàng)一篇文(wén)章我們學會(huì)了(le)打印分組的基本信息和(hé)将分組發送到(dào)指定端口輸出。今天我們就可以來(lái)實現(xiàn)一個簡單的交換功能(néng),完成兩台主機之間的正常通信了(le)。
     1)端口交換
     顧名思義,就是隻識别判斷端口号就将分組進行交換轉發,先實現(xiàn)一個基于端口的交換功能(néng)。固定邏輯隻能(néng)實現(xiàn)固定的兩個端口交換,我們可以将要交換的兩個端口從(cóng)程序啓動時(shí)作(zuò)爲參數輸入,這(zhè)樣就可以在啓動命令時(shí)按需要指定要交換的兩個端口參數了(le)。
     增加兩個端口變量的全局定義,并在main函數的參數輸入中獲取輸入的值,如:

/*端口交換要使用(yòng)的兩個全局端口号變量*/
int port1 = 0,port2 = 0;

/*main函數中添加如下(xià)代碼*/
else if(argc == 5)
{
debug = atoi(argv[1]);
mid = atoi(argv[2]);
port1 = atoi(argv[3]);
port2 = atoi(argv[4]);
}

/*callback函數中添加如下(xià)代碼*/
if(pkt->um.inport == port1)
pkt->um.outport = port2;
else
pkt->um.outport = port1;

      2)驗證
     編譯代碼并執行生成文(wén)件命令,觀察打印消息。

root@HNXS:/home/hnxs/l2switch# make
gcc -o ul2switch main_ul2switch.c -lua -lreg -lpthread
root@HNXS:/home/hnxs/l2switch# ./ul2switch 1 130 0 2
fastU->REG Version:20180827,OpenBox HW Version:2020210329
fastU->Register UA to FAST Kernel! Wait Reply......
fastU->UA->pid:2132,mid:130,Register OK!
fastU->libua version:20180827
fastU->fast_ua_recv......
inport:2,dstmid:130,len:92,dmac:FF:FF:FF:FF:FF:FF,smac:B8:27:EB:C1:D1:39
pkt_send_normal->0xb5500470,outport:0,len:92
inport:0,dstmid:130,len:92,dmac:B8:27:EB:C1:D1:39,smac:B8:27:EB:D8:83:20
pkt_send_normal->0xb5500470,outport:2,len:92
inport:2,dstmid:130,len:130,dmac:B8:27:EB:D8:83:20,smac:B8:27:EB:C1:D1:39
pkt_send_normal->0xb5500470,outport:0,len:130
inport:2,dstmid:130,len:130,dmac:B8:27:EB:D8:83:20,smac:B8:27:EB:C1:D1:39
pkt_send_normal->0xb5500470,outport:0,len:130

     同時(shí),在一個測試主機上(shàng)ping另一台測試主機的IP,發現(xiàn)已經ping通了(le)。

64 bytes from 192.168.2.117: icmp_seq=10 ttl=64 time=2.02 ms
64 bytes from 192.168.2.117: icmp_seq=11 ttl=64 time=0.742 ms
64 bytes from 192.168.2.117: icmp_seq=12 ttl=64 time=0.597 ms

     3)思考
     從(cóng)上(shàng)述交換打印分析,前兩個報(bào)文(wén)應該是ARP分組,32字節metadata加60字節以太幀數據。第1個是廣播請(qǐng)求,第2個是單播應答(dá)。第3和(hé)第4個報(bào)文(wén)就是第1組ping的交互數據了(le),标準ping的98字節(130-32=98)。
     先不往大(dà)了(le)說,至少我們前面添加了(le)幾行代碼就實現(xiàn)了(le)我們的一個最基本的原型交換了(le),如果要換端口測試,隻需要在啓動命令時(shí)更改相應的端口号參數就行了(le)。那交換機端口多了(le),用(yòng)戶多了(le)之後呢(ne)?我們豈不是要不斷回來(lái)的啓動程序和(hé)設置端口來(lái)保證他(tā)們通信呢(ne)?這(zhè)是不是跟解放(fàng)前的電話(huà)接線員工(gōng)作(zuò)有點類似?接線員接到(dào)電話(huà)後,先要詢問打電話(huà)的人要打給誰,然後再把線給連過去。當然,原來(lái)的電話(huà)通信與分組交換還是有些(xiē)較大(dà)區(qū)别,隻是類比一下(xià),不擴展細說。
      在分組交換的頭部攜帶有該分組要去往的目的地址,我們管他(tā)叫目的MAC地址。在以太網網絡中,任意一個通信終端都必須具備一個唯一的MAC地址,用(yòng)作(zuò)通信内容标識。在基于端口交換的基礎上(shàng),我們也(yě)可以很(hěn)容易的實現(xiàn)一個基于MAC地址的簡單交換功能(néng)。至于爲什(shén)麽選目的MAC作(zuò)爲交換判斷參數,大(dà)家細想肯定能(néng)明(míng)白(bái)。
      1)MAC交換
     根據以太網幀格式定義,從(cóng)分組頭部位置提取目的MAC作(zuò)爲判斷參數,實現(xiàn)一個基于MAC地址的交換功能(néng)。既然要根據目的MAC地址來(lái)做轉發,我們需要知(zhī)道(dào)哪一個MAC地址的主機連接在交換機的哪一個端口上(shàng)面,假設我們已經獲取了(le)這(zhè)些(xiē)信息如下(xià):

主機MAC地址:B8:27:EB:D8:83:20,交換機端口:0
主機MAC地址:B8:27:EB:C1:D1:39,交換機端口:2

替換原來(lái)端口交換的邏輯代碼,替換代碼如下(xià):

/*新增兩個MAC的内存格式定義,與S4平台(ARM)相關哦*/
u64 mac1 = 0x2083D8EB27B8,mac2 = 0x39D1C1EB27B8;

/*注釋原來(lái)端口轉發邏輯,添加MAC轉發邏輯*/
if(!ether_addr_equal(pkt->data,(u8 *)&mac1))
pkt->um.outport = 0;
else if(!ether_addr_equal(pkt->data,(u8 *)&mac2))
pkt->um.outport = 2;

     ether_addr_equal函數是判斷兩個MAC地址是否相等,詳情參閱代碼。
     兩個MAC地址的定義準确來(lái)說要根據MAC的順序方式表示後再做網絡序轉換,爲簡化邏輯和(hé)方便驗證,直接定義成了(le)小(xiǎo)端平台下(xià)反序方式,這(zhè)樣正好(hǎo)跟網絡序的MAC地址對(duì)比相等。關于平台數據的大(dà)小(xiǎo)端的問題或主機序與網絡序問題,請(qǐng)網上(shàng)搜索學習。
     2)驗證
編譯代碼并執行生成文(wén)件命令,觀察打印消息。

root@HNXS:/home/hnxs/l2switch# make
gcc -o ul2switch main_ul2switch.c -lua -lreg -lpthread
root@HNXS:/home/hnxs/l2switch# ./ul2switch
fastU->REG Version:20180827,OpenBox HW Version:2020210329
fastU->Register UA to FAST Kernel! Wait Reply......
fastU->UA->pid:2255,mid:129,Register OK!
fastU->libua version:20180827
fastU->fast_ua_recv......
inport:0,dstmid:129,len:92,dmac:FF:FF:FF:FF:FF:FF,smac:B8:27:EB:D8:83:20
pkt_send_normal->0xb5400470,outport:0,len:92
inport:0,dstmid:129,len:92,dmac:FF:FF:FF:FF:FF:FF,smac:B8:27:EB:D8:83:20
pkt_send_normal->0xb5400470,outport:0,len:92
inport:0,dstmid:129,len:92,dmac:FF:FF:FF:FF:FF:FF,smac:B8:27:EB:D8:83:20
pkt_send_normal->0xb5400470,outport:0,len:92

     同時(shí),在2端口測試主機上(shàng)ping另一台測試主機的IP,發現(xiàn)ping不通哦。這(zhè)是因爲我們現(xiàn)在的邏輯沒有考慮ARP廣播MAC地址的處理(lǐ)邏輯,導緻其無法正常轉發。本節暫不處理(lǐ)廣播的泛洪轉發功能(néng),後續文(wén)章中與組播一起讨論。
     那如何讓兩邊主機不發ARP廣播直接發ping的分組呢(ne)?了(le)解網絡通信原理(lǐ)的人都知(zhī)道(dào),這(zhè)個廣播是在ping之前發出的MAC地址學習分組,如果沒有學習到(dào)對(duì)端的MAC地址,則ping的分組無法完成二層協議(yì)的封裝,無法從(cóng)協議(yì)棧發出。使用(yòng)如下(xià)命令分别在兩台主機上(shàng)進行對(duì)端IP與對(duì)端MAC的靜态綁定設置,ping的分組便能(néng)正常發出了(le)。

/*192.168.2.115主機執行*/
#arp –s 192.168.2.117 b8:27:eb:d8:83:20
/*192.168.2.117主機執行*/
#arp –s 192.168.2.115 b8:27:eb:c1:d1:39

     現(xiàn)在,在任意一台主機上(shàng)執行ping均能(néng)可以看(kàn)到(dào)ping通了(le)。
     3)思考
     我們現(xiàn)在終于可以根據主機的MAC地址來(lái)進行分組交換轉發了(le),但(dàn)這(zhè)隻是兩台主機的固定交換轉發,如果機器MAC多了(le)怎麽辦?如果機器連接交換機的端口變了(le)怎麽辦?我們需要有一張記錄表,能(néng)夠記錄哪個MAC地址在哪個端口就好(hǎo)了(le),通過每個分組的目的MAC來(lái)查找其對(duì)應的輸出端口,這(zhè)樣就很(hěn)容易實現(xiàn)分組交換了(le)。
     1)交換過程的核心數據字段
     從(cóng)上(shàng)述實驗可以看(kàn)出,目前交換裏面用(yòng)到(dào)的就兩個字段,一個是端口号,另一個是MAC地址。那目的MAC地址與輸出端口号從(cóng)哪獲得?其實就是從(cóng)分組頭的源MAC地址和(hé)輸入端口轉換變成目的MAC和(hé)輸出端口。故在交換過程中,其核心數據就2個:端口号和(hé)MAC地址。
     2)MAC轉發表設計(jì)與驗證
     MAC轉發表就是我們前面提到(dào)的記錄表,這(zhè)張表記錄了(le)一個MAC地址與其對(duì)應端口号的綁定關系,這(zhè)一關系要從(cóng)輸入分組數據中提取而來(lái),由分組的輸入端口與源MAC地址組成這(zhè)一綁定關系,在查表中便可通過目的MAC來(lái)獲取其正确的輸出端口了(le)。下(xià)一篇文(wén)章我們聊一下(xià)MAC轉發表的設計(jì)。
      歡迎您和(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ǐ)。