网源设备及带内监控协议代理服务器设计-dcc over ip

                    协议转换代理服务器设计——虚拟网卡实现技术

                                        北京华环电子---任晓亮,2016/09/24

一.  虚拟网关概念

二.  网卡的工作流程

三.  内核配置支持虚拟网卡

四.  应用层代码

五.  使用案例

六.  参考文档

https://www.kernel.org/doc/Documentation/networking/tuntap.txt

 方案: SDH - -----》dcc监控通道------》数据ip封装 ------》虚拟网卡 ---》linux 协议栈 -----》以太网传输

一.   概念

再上次交流中,我们知道了用户空间跟内核空间的数据交互的n多种方法,这一节我们在来讲一个方法,在linux下,要实现 内核空间 和 用户空间 数据的交互,有多种方式:可以通用socket创建特殊套接字,利用套接字实现数据交互;通过proc文件系统创建文件来进行数据交互;还可以使用设备文件的方式,访问设备文件会调用设备驱动相应的例程,设备驱动本身就是 内核空间 和 用户空间 的一个接口,Tun/tap驱动就是利用设备文件实现用户空间 和 内核空间 的数据交互。

Tun/Tap都是虚拟网卡,没有直接映射到物理网卡,是一种纯软件的实现。Tun是三层虚拟设备,能够处理三层即IP包,Tap是二层设备,能处理链路层网络包如以太网包。使用虚拟网络设备,可以实现隧道,如OpenVPN的实现。

二.   工作流程

Tun/tap 驱动程序实现了虚拟网卡的功能,tun表示虚拟的是点对点设备,tap表示虚拟的是以太网设备,这两种设备针对网络包实施不同的封装。 利用tun/tap 驱动,可以将tcp/ip协议栈处理好的网络分包传给任何一个使用tun/tap驱动的进程,由进程重新处理后再发到物理链路中。

做为虚拟网卡驱动,Tun/Tap驱动程序的数据接收和发送并不直接和真实网卡打交道, 他在Linux内核中添加了一个TUN/TAP虚拟网络设备的驱动程序和一个与之相关连的字符设备 /dev/net/tun,字符设备tun作为用户空间和内核空间交换数据的接口。当内核将数据包发送到虚拟网络设备时,数据包被保存在设备相关的一个队列中,直到用户空间程序通过打开的字符设备tun的描述符读取时,它才会被拷贝到用户空间的缓冲区中,其效果就相当于,数据包直接发送到了用户空间。通过系统调用write发送数据包时其原理与此类似。

 



上面的图中,左右两边分别为两台机器。一台有一块物理网卡配置了IP:172.16.1.11,这台机器的系统里有一个Tun(以Tun为例,不讲Tap了)设备,配置了IP:192.168.1.11;另一台的一块物理网卡配置了IP:172.16.1.12,系统里有一个Tun设备并配置了IP:192.168.1.12。

左边Linux系统里有一个Application,绑定到端口地址为: 192.168.1.11:5000,右边Linux也有一个Application,绑定到端口地址为:192.168.1.12:5000,显然它们绑定的都是Tun设备的IP,接着它们就通过这两个地址通信了。

假设左边的Application要给右边的Application发送一个数据包,流程是这样的:

左边的Application并不知道什么虚拟网络设备,它只知道往"192.168.1.12:5000"这个地址发送,左边主机系统首先按正常的发包过程处理,比如判断目的主机是不是位于同一网段等等,然后数据包就在Linux的网络协议栈中穿行。Tun设备并不是真实的物理网卡,它不知道把数据包往哪里送,但是这些经过了Linux网络协议栈的数据可以从Tun设备的文件描述符中读取到,图中的“User Program”就是监听这个描述符等待读取数据的。这个“UserProgram”程序绑定的端口地址是:172.16.1.11:6000,每当它从Tun设备读到数据的时候,就把这些数据从物理网卡发送出去,目标地址是右边的:172.168.1.12:6000。

数据到达右边的系统,经过网络协议栈之后到达“UserProgram”应用进程,“User Program”将接收到的数据往Tun设备对应的文件描述符写入。对于Tun设备来说,“写入”就像是物理网卡接受到数据包一样,因此这些接收到的数据又进入了Linux的网络协议栈,最终到达右边的Application。

可能有人迷糊了,这里的Application是指各种各样的用户程序,如ping工具。“User Program”是用来辅助Tun设备来实现隧道功能的,可以想象成是OpenVPN进程,没有它隧道就废了。

 

三.   内核配置驱动支持

DeviceDrivers => Network device support => Universal TUN/TAP device driversupport


四.   数据结构参数说明

struct tun_struct {

   char       name[8]; //设备名

   unsigned long       flags; //区分tun和tap设备

   struct fasync_struct   *fasync; //文件异步通知结构

   wait_queue_head_t   read_wait;//等待队列

   struct net_device   dev;  //linux网络设备结构

   struct sk_buff_head    txq;//网络缓冲区队列

   struct net_device_stats  stats; //网卡状态信息结构

};

为了使用TUN/TAP设备,我们必须包含特定的头文件linux/if_tun.h,如5行所示。在21行,我们打开了字符设备/dev/net/tun。接下来我们需要为ioctl的TUNSETIFF命令初始化一个结构体ifr,一般的时候我们只需要关心其中的两个成员ifr_name,ifr_flags。ifr_name定义了要创建或者是打开的虚拟网络设备的名字,如果它为空或者是此网络设备不存在,内核将新建一个虚拟网络设备,并返回新建的虚拟网络设备的名字,同时文件描述符fd也将和此网络设备建立起关联。如果并没有指定网络设备的名字,内核将根据其类型自动选择tunXX和tapXX作为其名字。ifr_flags用来描述网络设备的一些属性,比如说是点对点设备还是以太网设备。详细的选项解释如下:

§       IFF_TUN:创建一个点对点设备

§       IFF_TAP:创建一个以太网设备

§       IFF_NO_PI:不包含包信息,默认的每个数据包当传到用户空间时,都将包含一个附加的包头来保存包信息

§       IFF_ONE_QUEUE:采用单一队列模式,即当数据包队列满的时候,由虚拟网络设备自已丢弃以后的数据包直到数据包队列再有空闲。

配置的时候,IFF_TUN和IFF_TAP必须择一,其他选项则可任意组合。其中IFF_NO_PI没有开启时所附加的包信息头如下:

Struct tun_pi
{
    unsigned short flags;
    unsigned short proto;
};

目前,flags只在收取数据包的时候有效,当它的TUN_PKT_STRIP标志被置时,表示当前的用户空间缓冲区太小,以致数据包被截断。proto成员表示发送/接收的数据包的协议。

上面代码中的文件描述符fd除了支持TUN_SETIFF和其他的常规ioctl命令外,还支持以下命令:

§       TUNSETNOCSUM:不做校验和校验。参数为int型的bool值。

§       TUNSETPERSIST:
把对应网络设备设置成持续模式,默认的虚拟网络设备,当其相关的文件符被关闭时,也将会伴随着与之相关的路由等信息同时消失。如果设置成持续模式,那么它将会被保留供以后使用。参数为int型的bool值。

§       TUNSETOWNER:设置网络设备的属主。参数类型为uid_t。

§       TUNSETLINK:设置网络设备的链路类型,此命令只有在虚拟网络设备关闭的情况下有效。参数为int型。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值