小谈IP Over PCI 的开发

来源:互联网 发布:烟袋斜街10号 网络剧 编辑:程序博客网 时间:2024/05/01 02:26
 
                 小谈IP Over PCI 开发
康华 :主要从事 Linux 操作系统内核、虚拟机、Linux 技术标准、计算机安全、软件测试等领域的研究与开发工作,曾就职 MII-HP 软件实验室 瞬联软件公司/MOTOROLA,现就职于Lenovo研究院 。其所合写的Linux专栏见http://www.csdn.net/subject/linux/。 如果需要可以联系通过 kanghua151@msn.com (MSN)联系我.       
        在本文中,我将前几天开发IP Over PCI 模块时的一些过程和认识与大家共享,另外在文章最后也给出一个简单的Demo模块供朋友们消遣。
        先来说说什么是IP Over PCI吧。 事情的经过是这样的——我们的通讯系统架构是由一个组插在同一个CompactPci总线上的板卡组成,它们之间可以通过读写PCI空间,进行数据交换(CompactPCI是PCI协议的一种扩展,从软件角度讲两者对开发者没什么区别,呵呵) 。
        由于我们多数板子的Flash存储空间有限,难以存放较为完整的文件系统。所以只想在一个配置有较大Flash的板子上安装Linux系统所需的文件系统,而让其它板子通过NFS方式使用大板上的文件系统。这样做很大程度的节约了各各个 小板的存储空间,可也带来了一个新问题:NFS需要TCP/IP协议栈支持,需要每个板子都有IP地址。
        Thanks Goodness!Linux 内核本身已经含有了对TCP/IP协议栈的支持,不需要我们操心实现了请输入大于10个字符的资源描述。剩下,我们唯一要做的就是让每个板子都有一个IP地址。要满足这个目的,最直接的方法就是为小板开发一个虚拟网卡,这样有了IP地址,就可以通过TCP/IP协议栈进行通讯的了。
         虚拟网卡的接口要求很简单,只要能够把协议栈送下来的IP包写到CPCI(Compact PCI)地址空间,即从虚拟网卡发送出去了;同时也能将其它虚拟网卡发送到CPCI地址空间的IP包读出来,并送到上层协议栈上。
 

虚拟网卡

CompactPCI

虚拟网卡

虚拟网卡

虚拟网卡

NFS

NFS

NFS

NFS


 
                                                  架构图
        
          虚拟网卡的实现我参照LLD中的例子,相信你也能够很快实现。至于从CPCI空间读写数据的实现是体系结构相关的,也没什么难的,不费笔墨了。这里我所以介绍IP Over PCI是希望能抛砖引玉,供大家开阔思路,你不妨想想,Over serial等等实现方法。
           呵呵,下面给出我做的一个demo 程序<vnetdemo.tar>IP Over FIFO (注:该程序运行于2.4.18内核,本网站的其它程序也都开发于2.4.18内核,不过移植到2.6内核也不是难事)。
 
        IP Over  FIFO不用解释,也可知道就是用FIFO命名管道来模拟以太网络,我之所以采用FIFO也是为了方便大家在单机上实验,纯用软件模拟――虚拟的网卡,虚拟的线       
         这个程序有两个一样的子文件组成 ,它们各被编译成一个虚拟网卡模块sn0 和 sn1(我们程序由LDD的snull程序演化而来,其中命名等都保持不变),你只需要分别加载,便可拥有两个虚拟网卡(ifconfig –a可看到它俩,当然你也可以配置它们的IP地址,方法和操作真网卡无异)。 NFS也就可以运行在其上了。
     
          但是要想在同一机器中运行测试这两个网卡,且让它们通讯。就需要在网卡发送时对源地址和目的地址的IP做写手脚 (在实际应用中不同板子之间运行时,不需要如此),其中原因在LDD中的网络驱动程序一章有很完整的解释,大家一定要去看看(开始我漏看了,就一直没能把包从虚拟网卡发出去),检测方法也可照LDD中的ping地址)。
           程序的主干采用了LDD中snull实例的实现,其中不同的地方有三个需要注意:第一点是虚拟网卡无法触发中断,因此IP包的接收(从FIFO中读取IP包)是采用了一个内核线程做轮训读取数据包;第二点是我们利用了两个FIFO管道文件(mkfifo或mknod命令可生成管道文件)模拟双向传输的网线。每个管道两头都有不同的虚拟网卡读写,只是两个管道读写方相反;第三点是我们需要在内核中读写文件,由于有空间保护问题(有一个断言会判断系统调用的参数地址空间是否在用户空间),因此从内核读写时需要改变空间检测的范围,具体做法是调用前后加上如下语句:
                             fs = ;
                            set_fs (get_ds());
                            系统调用,如sys_open()
                            set_fs(fs);
          就说这些吧!一切真知都来源于实践,希望大家多动脑筋来,多动手。
 
补记: 实例代码运行步骤
              1 执行 make ,编译完成会生成两个vnetdrv1.o 和vnetdrv2.o两个虚拟网卡模块。
              2 在当前目录下执行 mkfifo fifonet1;mkfifo fifonet2 生成两个用于模拟双向网线的命名管道文件。
              3 执行insmod vnetdrv1.o ; insmod vnetdrv2.o ,注册模块到内核,此刻系统中添加了sn0和sn1两个虚拟网卡。
              4 执行 ifconfig sn0 192.168.0.1 和ifconfig sn1 192.168.1.2 ,配置网卡 到两个网段。
       5 执行ping -c 2 192.168.0.2 数据将从在两个虚拟网卡间传送。