openVswitch(OVS)源代码分析之工作流程(收发数据包)

前面已经把分析openVswitch源代码的基础(openVswitch(OVS)源代码分析之数据结构)写得非常清楚了,虽然访问的人比较少,也因此让我看到了一个现象:第一篇,openVswitch(OVS)源代码分析之简介其实就是介绍了下有关于云计算现状和openVswitch的各个组成模块,还有笼统的介绍了下其工作流程,个人感觉对于学习openVswitch源代码来说没有多大含金量。云计算现状是根据公司发展得到的个人体会,对学习openVswitch源代码其实没什么帮助;openVswitch各个组成模块到网上一搜一大堆,更别说什么含金量了;最后唯一一点还算过的去的就是openVswitch工作流程图,对从宏观方面来了解整个openVswitch来说还算是有点帮助的。但整体感觉对于学openVswitch源代码没有多少实质性的帮助,可是访问它的人就比较多。相反,第二篇,openVswitch(OVS)源代码分析之数据结构分析了整个openVswitch源代码中涉及到的主要数据结构,这可是花了我不少精力。它也是分析整个源代码的重要基础,更或者说可以把它当做分析openVswitch源代码的字典工具。可是访问它的人数却是少的可怜,为什么会这样呢?

网上有很多blog写有关于openVswitch的,但是绝大部分只是介绍openVswitch以及怎么安装配置它,或者是一些命令的解释。对于源代码的分析是非常少的,至少我开始学习openVswitch时在网上搜资料那会是这样的。因此对于一个开始接触学习openVswitch源代码的初学者来说是非常困难的,什么资料都没有(当然官网上还是有些资料得,如果你英文够好,看官网的资料也是个不错的选择),只得从头开始去分析,可是要想想openVswitch是由一个世界级的杰出团队花几年的时间设计而成的,如果要从零开始学习分析它,要到猴年马月。所幸的是我开始学的时候,公司前辈们提供了些学习心得以及结构资料,所以在此我也把自己的学习心得和一些理解和大家分享。如有不正确之处,望大家指正,谢谢!!!

言归正传,基础已经学习过了,下面来正真分析下openVswitch的工作流程源代码。

首先是数据包的接受函数,这是在加载网卡时把网卡绑定到openVswitch端口上(ovs-vsctl add-port br0 eth0),绑定后每当有数据包过来时,都会调用该函数,把数据包传送给这个函数去处理。而不是像开始那样(未绑定前)把数据包往内核网络协议栈中发送,让内核协议栈去处理。openVswitch中数据包接受函数为:void
ovs_vport_receive(struct vport *vport, struct sk_buff *skb);函数,该函数所在位置为:datapath/vport.c中。实现如下:

// 数据包接受函数,绑定网卡后,所有数据包都是从这个函数作为入口传入到openVswitch中去处理的,
// 可以说这是openVswitch的入口点。参数vport:数据包从哪个端口进来的;参数skb:数据包的地址指针
void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
{
	struct pcpu_tstats *stats; // 其实这个东西一直没弄明白,大概作用是维护CPU的锁状态 

	stats = this_cpu_ptr(vport->percpu_stats); // 开始获取到CPU的锁状态,这和linux内核中的自旋锁类似
	u64_stats_update_begin(&stats->syncp); // 开始上锁
	stats->rx_packets++; // 统计数据包的个数
	stats->rx_bytes += skb->len; // 记录数据包中数据的大小
	u64_stats_update_end(&stats->syncp);// 结束锁状态

	if (!(vport->ops->flags & VPORT_F_TUN_ID)) // 这是种状态处理
		OVS_CB(skb)->tun_key = NULL;

// 其实呢这个函数中下面这行代码才是关键,如果不是研究openVswitch而是为了工作,个人觉得没必要(估计也不可能)
// 去弄清楚每条代码的作用。只要知道大概是什么意思,关键代码有什么作用,如果要添加自己的代码时,该往哪个地方添加就可以了。
// 下面这行代码是处理数据包的函数调用,是整个openVswitch的核心部分,传入的参数和接受数据包函数是一样的。
	ovs_dp_process_received_packet(vport, skb);
}

俗话说有接必有还,有进必有出嘛。上面的是数据包进入openVswitch的函数,那一定有其对应的出openVswitch的函数。数据包进入openVswitch后会调用函数ovs_dp_process_received_packet(vport,skb);对数据包进行处理,到后期会分析到,这个函数对数据包进行流表的匹配,然后执行相应的action。其中action动作会操作对数据包进行一些修改,然后再把数据包发送出去,这时就会调用vport.c中的数据包发送函数: ovs_vport_send(struct
vport *vport, struct sk_buff *skb);来把数据包发送到端口绑定的网卡设备上去,然后网卡驱动就好把数据包中的数据发送出去。当然也有些action会把数据包直接向上层应用发送。下面来分析下数据包发送函数的实现,函数所在位置为:datapath/vport.c中。

// 这是数据包发送函数。参数vport:指定由哪个端口发送出去;参数skb:指定把哪个数据包发送出去
int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
{
// 这是我自己加的代码,为了过滤掉ARP数据包。这里额外的插一句,不管在什么源代码中添加自己的代码时
// 都要在代码开头处做上自己的标识,因为这样不仅便于自己修改和调试、维护,而且也让其他人便于理解
       /*===========yuzhihui:==============*/
	if (0x806 == ntohs(skb->protocol)) {
          arp_proc_send(vport,skb);// 自定义了一个函数处理了ARP数据包
	}
	// 在前篇数据结构中讲了ops是vport结构中的一些操作函数的函数指针集合结构体
        // 所以vport->ops->send()是函数指针来调用函数,把数据包发送出去
	int sent = vport->ops->send(vport, skb);

	if (likely(sent)) { // 定义了一个判断宏likely(),如果发送成功执行下面
		struct pcpu_tstats *stats; // 下面的这些代码是不是觉得非常眼熟,没错就是接受函数中的那些代码

		stats = this_cpu_ptr(vport->percpu_stats);

		u64_stats_update_begin(&stats->syncp);
		stats->tx_packets++;
		stats->tx_bytes += sent;
		u64_stats_update_end(&stats->syncp);
	}
	return sent; // 返回的sent是已经发送成功的数据长度
}

这两个函数就是openVswitch中收发数据包函数了,对这两个函数没有完全去分析它的所有代码,这也不是我的本意,我只是想让初学者知道这是数据包进入和离开openVswitch的函数。其实知道了这个是非常有用的,因为不管你是什么数据包,只要是到该主机的(当然了包括主机内的各种虚拟机及服务器),全部都会经过这两个函数(对于接受的数据时一定要进过接受函数的,但是发送数据包有时候到不了发送函数的),那么要对数据包进行怎么样的操作那就全看你想要什么操作了。

在这两个函数中对数据包操作举例:

数据包接受函数中操作:如果你要阻断和某个IP主机间的通信(或者对某个IP主机数据包进行特殊处理),那么你可以在数据进入openVswitch的入口函数(ovs_vport_receive(struct vport *vport, struct sk_buff *skb);)中进行处理,判断数据包中提取到的IP对比,如果是指定IP则把这个数据包直接销毁掉(也可以自己定义函数做些特殊操作)。这样就可以对整个数据进行控制。

数据包发送函数中操作:就像上面的函数中我自己写的那些代码一样,提取数据包中数据包类型进行判断,当判断如果是ARP数据包时,则调用我自定义的 arp_proc_send(vport,skb);函数进行去处理,而不是贸然的直接把它发送出去,因为你不知道该数据包发送的端口是什么类型的。如果是公网IP端口,那么就在自定义函数中直接把这个数据包掐死掉(ARP数据包是在局域网内作用的,就算发到公网上也会被处理掉的);如果是发送到外层局域网中或者是相连的服务器中,则修改数据包中的目的Mac地址进行洪发;又如果是个ARP请求数据包,则把该数据包修改为应答包,再原路发送回去,等等情况;这些操作控制都是在发送数据包函数中做的手脚。

以上就是openVswitch(OVS)工作流程中的数据包收发函数,经过大概的分析和应用举例说明,我想对于初学者来说应该知道大概在哪个地方添加自己的代码,实现自己的功能要求了。

转载请注明原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/39298321

如有不正确之处,望大家指正,谢谢!!!

时间: 2024-10-12 12:46:20

openVswitch(OVS)源代码分析之工作流程(收发数据包)的相关文章

openVswitch(OVS)源代码分析之工作流程(数据包处理)

上篇分析到数据包的收发,这篇开始着手分析数据包的处理问题.在openVswitch中数据包的处理是其核心技术,该技术分为三部分来实现:第一.根据skb数据包提取相关信息封装成key值:第二.根据提取到key值和skb数据包进行流表的匹配:第三.根据匹配到的流表做相应的action操作(若没匹配到则调用函数往用户空间传递数据包):其具体的代码实现在 datapath/datapath.c 中的,函数为: void ovs_dp_process_received_packet(struct vpor

openVswitch(OVS)源码分析之工作流程(哈希桶结构体的解释)

这篇blog是专门解决前篇openVswitch(OVS)源码分析之工作流程(哈希桶结构体的疑惑)中提到的哈希桶结构flex_array结构体成员变量含义的问题. 引用下前篇blog中分析讨论得到的flex_array结构体成员变量的含义结论: struct { int element_size; // 这是flex_array_part结构体存放的哈希头指针的大小 int total_nr_elements; // 这是全部flex_array_part结构体中的哈希头指针的总个数 int e

Monkey源代码分析之执行流程

在<MonkeyRunner源代码分析之与Android设备通讯方式>中.我们谈及到MonkeyRunner控制目标android设备有多种方法.当中之中的一个就是在目标机器启动一个monkey服务来监听指定的一个port,然后monkeyrunner再连接上这个port来发送命令.驱动monkey去完毕对应的工作. 当时我们仅仅分析了monkeyrunner这个client的代码是怎么实现这一点的,但没有谈monkey那边是怎样接受命令,接受到命令又是怎样处理的. 所以自己打开源代码看了一个

Spark SQL源代码分析之核心流程

/** Spark SQL源代码分析系列文章*/ 自从去年Spark Submit 2013 Michael Armbrust分享了他的Catalyst,到至今1年多了,Spark SQL的贡献者从几人到了几十人,并且发展速度异常迅猛,究其原因,个人觉得有下面2点: 1.整合:将SQL类型的查询语言整合到 Spark 的核心RDD概念里.这样能够应用于多种任务,流处理,批处理,包含机器学习里都能够引入Sql. 2.效率:由于Shark受到hive的编程模型限制,无法再继续优化来适应Spark模型

nodejs的Express框架源码分析、工作流程分析

1.Express的编写流程 2.Express关键api的使用及其作用分析 app.use(middleware); connect package分析 function fn(req,res,next)的定义及其使用,next的定义,及其运转流程. 3.Express源代码分析,依赖库分析

openvxn工作原理与数据包流向

很长时间没写博客,没错,我又被拉去做外包了,不多BB,直接上干货.也许你面试需要openvxn区别与传统vxn,它工作在IP层,OpenVxN是一款基于SSL的开源VxN软件,它实现了利用SSL来保证网络通讯安全性的目的,同时避免了传统SSL VxN仅提供简单的Web应用的不足,它具有支持各种应用协议,支持Windows,Linux,BSD,MAC OS等多平台的特点. 环境说明A为客户端192.168.1.2B为服务端10.0.0.2 已经在配置文件中加入了push "redirect-gat

OpenVswitch(OVS)源代码分析之简介

云计算是现在IT行业比较流行的,但真正什么是云计算业界也没有个什么统一的定义(很多公司都是根据自己的利益狭隘的定义云计算),更别说什么标准规范了.所以现在就有很多人说云计算只不过是个幌子,是个嘘头,没点实用的,嘴上说说而已,虽然我也不太清楚什么叫做云计算,云计算的定义究竟是什么,但我根据我公司现在做的云计算产品来说,对于云计算服务还是懂些的.我觉得那并不是什么幌子.嘘头,但如果说这云计算技术还不太成熟,我倒还勉强认可的.若把云计算比作一个人的话,我个人觉得现在它正是二十岁的样子,到三十多岁就算是

浅析live555媒体库之工作流程介绍

live555项目的源代码包括四个基本的库,各种测试代码以及Media Server. 工作模块 四个基本的库分别是: UsageEnvironment  TaskScheduler, groupsock, liveMedia和BasicUsageEnvironment. 官网英文的基本介绍截图如下: 虽是英文的,但是难度不大,能看懂大致意思.这里多说一句,程序员还是要接触并学习英文,毕竟好的技术都是国外引进的.简单说下我的理解 UsageEnvironment   该类库是对系统环境的抽象,包

Monkey源代码分析之事件注入

本系列的上一篇文章<Monkey源代码分析之事件源>中我们描写叙述了monkey是怎么从事件源取得命令.然后将命令转换成事件放到事件队列里面的.可是到如今位置我们还没有了解monkey里面的事件是怎么一回事,本篇文章就以这个问题作为切入点.尝试去搞清楚monkey的event架构是怎么样的.然后为什么是这样架构的,以及它又是怎么注入事件来触发点击等动作的. 在看这篇文章之前,希望大家最好先去看下另外几篇博文,这样理解起来就会更easy更清晰了: <Monkey源代码分析番外篇之Andro