说点题外话(我不仅把这些当作技术文章,还当作工作笔记,甚至当作生活日记),最近工作在制作各种docker镜像,有点小忙。而工作剩余时间又在看汇编,和操作系统知识,所以对ovs就没什么时间去了解了。不过还好,这周空闲下来了,就看了下ovs中的upcall()函数调用。
话说现在ovs已经出了2.xxx版本了,我稍微浏览了下,发现有些函数名改变了,但其主要功能还是保留的。为了衔接前几篇blog,所以我还是选择下载1.xx版本的源代码来分析。我以前那套ovs源代码做了很多笔记,不过可惜搬公司的时候服务器坏掉了,所有数据都找不到了(因为分析这个源代码是个人行为、私事,所以也就没有去恢复硬盘了)。
还有个事要麻烦下,我分析这些源代码是以个人的观点和判断,我没有什么资料,就是一步一步的去分析,然后组成整个框架,其中当然免不了有些错误(人家是世界级团队完成的,你一个小程序员花这么点时间就想弄明白,那估计是不太可能的),所以我非常鼓励支持查资料的朋友仅仅是把我的分析当作一种参考,然后如果发现和我猜想的框架有问题时能及时告知我,谢谢!!
好了,下面正式谈谈和源代码有关的事了。我看了下upcall()函数的大体实现,其中主线是用Linux内核中的NetLink通信机制。而其中涉及到一些其他知识点,大部分在前面已经分析过了;但vlan知识点,在前面好像基本上没有提到,个人觉得这是个非常有价值的知识点,后续我会好好了解下。而有关ovs的前一篇openVswitch(OVS)源代码分析 upcall调用(之linux中的NetLink通信机制)我现在到回去看了看,感觉没有写好,有点懊恼。有些东西写的不够仔细,太注重代码的实现了,而没写好一些理论的东西。如果要了解upcall()函数,那些基础的结构体还是要重点了解下,所以我会修改前面的NetLink分析或者到后面再分析下理论知识。
现在来想下为什么有upcall()函数?因为比如当第一个数据包过来时(前期没有和这个数据包的ip主机通信过),ovs中没有任何有关于该主机的信息,更没有设置一些规则来处理接受到该主机的数据包。所以当第一次接受到这个数据包时,就要提取出数据包中一些信息,下发到用户空间去,让用户空间做些规则用来处理下次接收到的该类数据包。
下面开始看代码,还是从void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)函数开始切入吧。
if (unlikely(!flow)) {//查不到流表的情况
struct dp_upcall_info upcall;
upcall.cmd = OVS_PACKET_CMD_MISS; //包miss,表示这个包是没匹配到的
upcall.key = &key; //key值,对一个sk_buff网络包的特征数据进行提取组成的结构
upcall.userdata = NULL; // 传送给用户空间的数据
upcall.portid = p->upcall_portid; //传送给用户空间时使用的id号,netlink中已经说明
ovs_dp_upcall(dp, skb, &upcall); // 调用函数处理,本blog的主角
consume_skb(skb); // 释放掉包结构==》kfree_skb(skb)
stats_counter = &stats->n_missed; //对包的计算
goto out;
}
下面就是轮到今天的主角出场了:
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
const struct dp_upcall_info *upcall_info)
{
struct dp_