0731-84728105
15116127200
二层交换机原型设计与实现(三)
发布时间:2021-05-10
     二层交换机的主要功能(néng)就是在端口之间搬移分(fēn)组,当然是要根据正确的目标地址来搬移,涉及到以太网帧格式的解析、源和目的MAC地址的提取,MAC表的设计、查找和老化等等一系列的系统功能(néng)实现。我们开始设计交换机并不考虑那么多(duō),从简单入手,轻装上阵,你也许会走得更好。
     上一篇文(wén)章我们學(xué)会了打印分(fēn)组的基本信息和将分(fēn)组发送到指定端口输出。今天我们就可(kě)以来实现一个简单的交换功能(néng),完成两台主机之间的正常通信了。
     1)端口交换
     顾名思义,就是只识别判断端口号就将分(fēn)组进行交换转发,先实现一个基于端口的交换功能(néng)。固定逻辑只能(néng)实现固定的两个端口交换,我们可(kě)以将要交换的两个端口从程序启动时作為(wèi)参数输入,这样就可(kě)以在启动命令时按需要指定要交换的两个端口参数了。
     增加两个端口变量的全局定义,并在main函数的参数输入中获取输入的值,如:

/*端口交换要使用(yòng)的两个全局端口号变量*/
int port1 = 0,port2 = 0;

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

/*callback函数中添加如下代码*/
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

     同时,在一个测试主机上ping另一台测试主机的IP,发现已经ping通了。

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)思考
     从上述交换打印分(fēn)析,前两个报文(wén)应该是ARP分(fēn)组,32字节metadata加60字节以太帧数据。第1个是广播请求,第2个是单播应答(dá)。第3和第4个报文(wén)就是第1组ping的交互数据了,标准ping的98字节(130-32=98)。
     先不往大了说,至少我们前面添加了几行代码就实现了我们的一个最基本的原型交换了,如果要换端口测试,只需要在启动命令时更改相应的端口号参数就行了。那交换机端口多(duō)了,用(yòng)户多(duō)了之后呢(ne)?我们岂不是要不断回来的启动程序和设置端口来保证他(tā)们通信呢(ne)?这是不是跟解放前的電(diàn)话接線(xiàn)员工作有(yǒu)点类似?接線(xiàn)员接到電(diàn)话后,先要询问打電(diàn)话的人要打给谁,然后再把線(xiàn)给连过去。当然,原来的電(diàn)话通信与分(fēn)组交换还是有(yǒu)些较大區(qū)别,只是类比一下,不扩展细说。
      在分(fēn)组交换的头部携带有(yǒu)该分(fēn)组要去往的目的地址,我们管他(tā)叫目的MAC地址。在以太网网络中,任意一个通信终端都必须具备一个唯一的MAC地址,用(yòng)作通信内容标识。在基于端口交换的基础上,我们也可(kě)以很(hěn)容易的实现一个基于MAC地址的简单交换功能(néng)。至于為(wèi)什么选目的MAC作為(wèi)交换判断参数,大家细想肯定能(néng)明白。
      1)MAC交换
     根据以太网帧格式定义,从分(fēn)组头部位置提取目的MAC作為(wèi)判断参数,实现一个基于MAC地址的交换功能(néng)。既然要根据目的MAC地址来做转发,我们需要知道哪一个MAC地址的主机连接在交换机的哪一个端口上面,假设我们已经获取了这些信息如下:

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

替换原来端口交换的逻辑代码,替换代码如下:

/*新(xīn)增两个MAC的内存格式定义,与S4平台(ARM)相关哦*/
u64 mac1 = 0x2083D8EB27B8,mac2 = 0x39D1C1EB27B8;

/*注释原来端口转发逻辑,添加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地址的定义准确来说要根据MAC的顺序方式表示后再做网络序转换,為(wèi)简化逻辑和方便验证,直接定义成了小(xiǎo)端平台下反序方式,这样正好跟网络序的MAC地址对比相等。关于平台数据的大小(xiǎo)端的问题或主机序与网络序问题,请网上搜索學(xué)习。
     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

     同时,在2端口测试主机上ping另一台测试主机的IP,发现ping不通哦。这是因為(wèi)我们现在的逻辑没有(yǒu)考虑ARP广播MAC地址的处理(lǐ)逻辑,导致其无法正常转发。本节暂不处理(lǐ)广播的泛洪转发功能(néng),后续文(wén)章中与组播一起讨论。
     那如何让两边主机不发ARP广播直接发ping的分(fēn)组呢(ne)?了解网络通信原理(lǐ)的人都知道,这个广播是在ping之前发出的MAC地址學(xué)习分(fēn)组,如果没有(yǒu)學(xué)习到对端的MAC地址,则ping的分(fēn)组无法完成二层协议的封装,无法从协议栈发出。使用(yòng)如下命令分(fēn)别在两台主机上进行对端IP与对端MAC的静态绑定设置,ping的分(fēn)组便能(néng)正常发出了。

/*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

     现在,在任意一台主机上执行ping均能(néng)可(kě)以看到ping通了。
     3)思考
     我们现在终于可(kě)以根据主机的MAC地址来进行分(fēn)组交换转发了,但这只是两台主机的固定交换转发,如果机器MAC多(duō)了怎么办?如果机器连接交换机的端口变了怎么办?我们需要有(yǒu)一张记录表,能(néng)够记录哪个MAC地址在哪个端口就好了,通过每个分(fēn)组的目的MAC来查找其对应的输出端口,这样就很(hěn)容易实现分(fēn)组交换了。
     1)交换过程的核心数据字段
     从上述实验可(kě)以看出,目前交换里面用(yòng)到的就两个字段,一个是端口号,另一个是MAC地址。那目的MAC地址与输出端口号从哪获得?其实就是从分(fēn)组头的源MAC地址和输入端口转换变成目的MAC和输出端口。故在交换过程中,其核心数据就2个:端口号和MAC地址。
     2)MAC转发表设计与验证
     MAC转发表就是我们前面提到的记录表,这张表记录了一个MAC地址与其对应端口号的绑定关系,这一关系要从输入分(fēn)组数据中提取而来,由分(fēn)组的输入端口与源MAC地址组成这一绑定关系,在查表中便可(kě)通过目的MAC来获取其正确的输出端口了。下一篇文(wén)章我们聊一下MAC转发表的设计。
      欢迎您和學(xué)生们加入FAST开源项目群沟通与探讨,一起體(tǐ)验不一样的系统设计过程。请先加微信号15116127200后邀请入群。

关注FAST开源社區(qū)
FAST一一开源、开放、高速、高效、可(kě)编程、可(kě)定义!软硬件协同并行处理(lǐ)。
服務(wù)热線(xiàn)