一、概述
FAST架构的UA编程非常简单,有其固定的套路,核心部分两块,一是在main函数中把环境初始化好,注册UA的回调函数和配置硬件默认规则;二是在回调函数中专心处理分组数据,实现完整业务功能。
二层交换的分组接收由系统回调送入处理函数,后续交换相关的所有逻辑均在该函数里完成实现。
二、编译并验证示例代码
1)UA示例代码
网盘下载地址:https://pan.baidu.com/s/13zmKXeMnpUMsCiL5GAI7Vg
提取码:ehd7
目录:FAST开源社区/教学案例/连载公开课/二层交换机原型设计与实现
2)代码文件说明
二层交换代码目录为:/home/hnxs/l2switch/,其下共包括两个文件,其中一个为main_ul2switch.c主要包括UA的平台性处理代码和空的callback函数。另一个是C的编译文件Makefile文件,主要说明如何编译生成二层交换可执行命令。
3)编译文件说明
default:
gcc -o ul2switch main_ul2switch.c -lua -lreg -lpthread
clean:
rm -rf ul2switch
二层交换机编译需要使用到FAST的libreg、libua和系统的libpthread三个库的支持。
4)编译, 在/home/hnxs/l2switch/目录下输入以下命令:
root@HNXS:/home/hnxs/l2switch# make
系统输出如下:
gcc -o ul2switch main_ul2switch.c -lua -lreg -lpthread
当前目录会多产生一个ul2switch文件
root@HNXS:/home/hnxs/l2switch# ls
main_ul2switch.c Makefile ul2switch
5)执行验证,在/home/hnxs/l2switch/目录下输入以下命令:
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:3069,mid:129,Register OK!
fastU->libua version:20180827
fastU->fast_ua_recv......
显示上述结果说明系统平台代码执行正常。
三、梳理代码流程
1)C程序的主函数main
/*UA模块初始化*/
ua_init(mid);
/*配置硬件默认规则,将硬件所有报文送到模块ID为mid的进程处理*/
fast_reg_wr(FAST_ACTION_REG_ADDR|FAST_DEFAULT_RULE_ADDR,ACTION_SET_MID<<28|mid);
/*启动线程接收分派给UA进程的报文*/
fast_ua_recv();
/*主进程进入暂停状态,数据处理主要在回调函数*/
pause();
2)创建UA,注册callback
void ua_init(u8 mid)
{
int ret = 0;
/*向系统注册,自己进程处理报文模块ID为mid的所有报文*/
if((ret=fast_ua_init(mid,callback)))//UA模块实例化(输入参数1:接收模块ID号,输入参数2:接收报文的回调处理函数)
{
perror("fast_ua_init!\n");
exit (ret);//如果初始化失败,则需要打印失败信息,并将程序结束退出!
}
}
3)callback处理函数
int callback(struct fast_packet *pkt,int pkt_len)
{
return 0;
}
四、验证数据IO功能
1)打印接收分组metadata信息
FAST分组的数据格式请参考第一篇文章《二层交换机原型设计与实现》描述。在callback函数一开始,打印FAST分组的metadata信息和以太网协议的源和目的MAC地址信息。
xprintf("inport:%d,dstmid:%d,len:%d,dmac:%02X:%02X:%02X:%02X:%02X:%02X,smac:%02X:%02X:%02X:%02X:%02X:%02X\n",
pkt->um.inport,pkt->um.dstmid,pkt_len,pkt->data[0],pkt->data[1],pkt->data[2],pkt->data[3],pkt->data[4],pkt->data[5],pkt->data[6],pkt->data[7],pkt->data[8],pkt->data[9],pkt->data[10],pkt->data[11]);
2)调用发送函数发送分组
调用FAST的分组发送函数,将接收到的一个分组从指定端口发出,要特别注意metadata字段的设置。
void pkt_send_normal(struct fast_packet *pkt,int pkt_len)
{
xprintf("pkt_send_normal->%p,outport:%d,len:%d\n",pkt,pkt->um.outport,pkt_len);
pkt->um.pktsrc = 1;/*报文来源为CPU输入,站在硬件角度*/
pkt->um.pktdst = 0;/*报文目的为硬件输出*/
pkt->um.dstmid = 5;/*直接从硬件GOE模块输出,不走解析、查表等模块*/
fast_ua_send(pkt,pkt_len);/*调用FAST API函数发送*/
}
该函数调用之前,必须将pkt->um.outport字段赋值,指定分组的输出端口号。
五、总结与下一步
1)核心函数callback
callback函数是整个UA的核心功能函数,是用户业务实现的开始位置。虽然我们今天只在该函数中做了两件事情,一是打印接收到的分组基本信息,二是将该分组发送到指定端口。但是,我们今天已经在该平台上实现了一个最简单的分组转发功能的原型系统了。
2)注释和备份的重要性
重新性不多说,只是在此特别的特别的强调一下。
3)实现简单交换逻辑功能
在如此简单的一个平台上,能快速实现硬件端口的分组接收和指定端口的分组发送,是不是网络功能的一大部分问题均已经解决?我们只需要关注我们具体业务的逻辑处理了,你到底是要实现交换还是路由?是普通二层交换还是SDN交换?是普通三层路由还是lisp路由或是segment路由,是不是一切均有可能?
不要高兴得太早,这只是万里长征的第一步,起点和终点的距离必须由自己的脚步来测量,一步也不能少。所以我们还是从简单的二层交换机开始,下一篇文章正式进入分组交换的设计。
欢迎您和学生们加入FAST开源项目群沟通与探讨,一起体验不一样的系统设计过程。请先加微信号15116127200后邀请入群。
![图片](https://i-blog.csdnimg.cn/blog_migrate/098649511c91f6a60050fd0a6be9ed1a.png)