Xen-network 学习笔记-2 (TechDiary-20110226)

 

开始写之前先记下几个与题目无关的知识吧,是在看代码的时候查到的:

首先是一个在内核代码中经常出现的宏:likely() and unlikely(), google了一下(看的资料为http://www.soidc.net/articles/1215484977397/20091220/1215945676298_1.html),明白了在内核代码中使用这两个宏,主要的目的是为了进行代码的优化,提高系统执行速度。

  比如 :

  

  这里就是程序员可以确定 a>b 在程序执行过程中出现的可能相比较大,因此使用了likely()告诉编译器fun1()函数的二进制代码紧跟在前面程序的后面,这样就cache在预取数据时就可以将fun1()函数的二进制代码拿到cache中。这样,也就增加了cache的命中率。

  同样的,unlikely()的作用就是告诉编译器,a<b 的可能性很小所以这里在编译时,将fun2()的二进制代码尽量不要和前边的编译在一块。

另外一个是BUG_ON(摘自http://dev.firnow.com/course/6_system/linux/Linuxjs/20110109/552421.html, 它是一个函数接口,一般开发人员自己实现相关函数内容,一般用来判断内核是否出现问题,如果参数为真的话,证明内核出现了bug,打印BUG信息,然后调用PANIC函数,让系统panic

还有一个就是我们在编内核的时候首先要先make menuconfig, menuconfig那个界面中有很多选项和说明,那么这些选项和说明是在哪里定义的呢?我们自己可不可以改或者加呢?我记得在《Linux那些事儿之我是PCI》一书中有看到相关的内容,这些内容是在每个文件夹下的Kconfig文件中定义的,把它们打开来看下也就一目了然了。对了,顺便再推荐下《Linux那些事儿之我是xxx》系列丛书吧,是fudanABC大牛写的,真的是写的太好了,那年看那个《..我是USB》看到实在是神魂颠倒,能把如此枯燥的驱动写成如小说一般实在是XXX啊。。。

 

好了,接下来是正题了,说实话,之前看代码看得真的是头都大了,特别是在netback里面,实在是搞不明白为什么在tx_submit()函数里面会有一个netif_rx()函数,而且之前完全没有看出backend里面是那里有把packet传出去,当时猜想rx这个函数把packet反正那个buffer上,然后由nativedevice driver进行轮询再发出去,不过当时也找不到真正的实现是怎么样的,由于知识的缺陷也不敢确定,也有很多迷惑的地方,之后实在没有办法了就发邮件给了netback.c的作者K.A.Fraser,没想到他如此之快就回复了,而且彻底让我搞懂了这是怎么回事,不愧是大牛啊!而且通过之后再查了一些资料,把其中Bridge-network这一点搞懂后,对于frontendbackend,以及backendphysical interface之间的联系终于差不多搞明白了,不知道是否完全正确,反正先记录下来,如果发现之后还有错误的地方再来回过来比较修改吧~~

按照我的看法,真实情况应该是这样子的:

首先要有一张在脑中的图(摘自Achieving High Throughput by Transparent Network Interface Virtualization on Multi-core Systems.pdf):

xen-networking-overview

 

也就是说netfrontnetback之间是通过I/O ringgrant tableevent-channel进行交互的,而netbackdom0中真实的device driver之间有一个bridge进行交互。

先从简单的开始,来看下右半边是如何实现的吧,我主要是想从代码角度来分析,可能比较枯燥,不过我想应该是最直观的了:

就从domU的一个数据包是如何发出去说起吧,首先在domUxennet_netdev_ops中注册了一个函数:

 

.ndo_start_xmit      = xennet_start_xmit,

 

上层应用需要发包的话会调用网络设备相对应的.ndo_start_xmit,即上面的这个函数:

 

static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)

 

 

 

在该函数中,主要先是写一个tx_request,并将访问它的权限赋给dom0,然后对包进行下处理,包括他checksum的选项,和extrainfo,主要是GSO( Generic Segmentation Offload)选项,顺便提下,该选项是为了把segmentation offload让硬件来做,为了减小内存的拷贝,系统会讲一个大包传到网卡上,当由于ethernet层有MTU这种限制,包必须被分成几个小包,即segmentation。而以该信息相关的就是一个叫xen_netif_extra_info的结构,如果需要GSO的话,则会在这个extra_info中记录每个分开的fragment应该是多大等等信息,之后start_xmit()中还会调用一个函数,xennet_make_frags(),会将跨page的requests分成多个fragments,然后放入np->tx_skbs中,之后就调用了RING_PUSH_REQUESTS_AND_CHECK_NOTIFY这个宏,也就是将request放到I/O ring中,之后根据返回的notify变量调用notify_remote_via_irq(np->netdev->irq),这个时候就发了一个hypercall陷到xen里面,这个时候netfront的任务就结束了,这个时候就轮到netback出场了,在netback.c中定义了一个tasklet,即将net_tx_action()设为net_tx_tasklet,之后在每次 netif_schedule_work之后,都会调用到这个函数,
 
在tx_action里,首先调用到的是一个net_tx_action_dealloc,这个函数我现在还不是很了解是干什么的,我想因该是处理已经完成的request,然后调用一下make_tx_response,在I/O ring上写上response,但是在这之前应该得先把这个packet发出去啊,不过调用tx_action_dealloc这个函数是在dealloc_cons != dealloc_prod的条件下进入的,所以一开始是不会进去的,所以可以先来看下之后的函数,其实这之间主要就是繁杂的数据操作了,主要是netback通过I/O ring获得tx_request以及里面包含的数据在grant_table中的reference和相应的operations,通过hypercall对数据进行map,最后tx_action函数调用到了net_tx_submit()这个函数,这个函数中对数据进行了处理和分析,最后调用到了netif_rx()函数,按照Fraser的说法:
The 'tx' and 'rx' naming scheme in netback is used from the point of view of the client VMs -- when a VM transmits a packet, netback processes it via net_tx_action, and injects it into domain-0 kernel's network stack for forwarding (usually via a software ethernet bridge to a physical network interface). Netif_Rx() is nothing more than the interface provided for network drivers to stuff packets up into the kernel's network stack.
不过这里还有一个问题,既然netif_rx()都是将packet放入kernel network stack中,那么从外部来的和从domU来的都要放到这个栈上,那么又是如何将这两个区分开来的呢?同样的,Fraser也回答了:
> one is when the package coming from outside network to the dom0(at this routine, the package just need to
> spread up to be processed by CPU),
Yes, the call to netif_rx() comes from within the physical network
interface's device driver.
> the other is from domU to dom0(where the dom0 need to send it out),
This is the netif_rx() call from within netback driver
>  so at what level that dom0 will recognize the different source of the package and handle it in two distinct ways? or
> the two different routine just stuff the packages up to different stack?
It's all the same network stack. The stack will inspect packet headers to decide where to forward the packet. In the common scenario in which packets are forwarded by etherbridge, the etherbridge code will inspect the destination MAC address and compare against its forwarding table
其他问题都搞明白了,就还剩下最后一个问题了,也是Fraser说的: How an Ethernet bridge works is something you can go read up on.
这一篇xenwiki的文章说的很清楚,包括bridge,route等等机制具体是如何实现的,我想等有机会再用自己的话来描述一遍吧~
今天先写到这,还有receive的部分,这是接下来的任务@@

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值