2010-04-14 设计文档
今天主要是把设计文档写了,虽然不知道怎么写,但是大概写了写,
1 功能描述
4over6隧道模块在整个linux系统中的作用是,将进入隧道的IPv4分组分装成IPv6隧道包,并发送出去;将收到的IPv6隧道包解封装,并根据情况转发至本地网络。由于项目的实际需求,只需要在cpe上面建立一个隧道,所以只存储了目的机器和本地机器的ipv6的地址,对于进入隧道发送模块的所有的包都会被封装成隧道包发送到目的机器。
2 文件结构
2.1 虚拟设备
虚拟设备是通过创建一个net_device结构体并注册来实现的。在一个net_device结构体里面,主要实现以下几个成员和回调函数:
成员 | 说明 |
char name[IFNAMSIZ]; | 该虚接口的设备名。通过ifconfig配置接口的时候调用。 |
int (*init)(struct net_device *dev); | 初始化函数。该函数在此设备结构初始化的时候由Linux系统调用。函数需要完成的事情是,为结构中用到的私有域分配空间,为结构各个域赋初始值,包括各参数和函数指针等。 |
unsigned short mtu; | 最大传输单位,在此处设置成与以太网相同,即1500 |
void *priv; | 私有数据。即结构中各函数可能用到的私有数据。在虚接口中,这部分包括一些统计数据(如收发字节数等)、对封装表的操作函数指针等。 |
int (*open) (struct net_device *dev); | 此函数的作用是启用该接口设备。具体来说,会在接口被ifconfig激活时调用。对于虚接口来说,由于不对具体的硬件操作,所以该接口的作用仅是设置一下标志位。 |
int (*stop) (struct net_device *dev); | 此函数用来停止虚接口。 |
Int (*do_ioctl) (struct net_device* dev, struct ifreq *ifr, int cmd) | 实现对接口的配置,通过ifreq结构传送控制命令。 |
int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev); | 这是虚接口最重要的一个函数,实现对IPv4分组的封装操作,其流程在前面已经描述过了,在此不再重复。 |
Struct net_device_stats* (*get_stats)(struct net_device *dev); | 获取统计信息,供ifconfig等调用 |
2.2 IPGRE协议
每一个协议都有一个唯一的协议号,协议的作用就是区分对协议进行处理的模块,在一个网络设备收到一个包了之后,查看这个包的协议类型,如果是ipv4就会给ipv4的模块。同理,当ipv4模块去掉ipv4的头部之后,也要查看头部上面的协议号,如果是TCP,就给TCP相关的协议。所以在本机接收到隧道包之后,需要在去掉ipv6头部之后给一个专门的协议模块在处理其他的东西。所以要新添加一个协议,新的协议号要和原来的协议不一样。由于在ipv6协议族里面没有GRE协议,所以可以使用GRE的协议号。
成员 | 说明 |
int (*handler)(struct sk_buff *skb); | 这是协议结构中最重要的一项,是用于处理该协议数据包的函数。对IPv6隧道包的解封装操作就在该函数中实现。借封装后,加入判断语句判断是否为组播包,如果是组播包,则调用组播处理函数。 |
void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, int code, int offset, __be32 info); | 错误处理函数。用于IP分组的出错识别和处理。具体来讲,用于接收ICMPv6报文,然后根据情况向IPv4主机发送ICMP报文。 |
3 隧道配置
隧道相关的整个模块已经被写成一个模块,编译成tunnel.ko。
首先,载入模块
#insmod tunnel.ko
然后,配置隧道接口的地址,并打开
#ifconfig tunnel46 219.243.40.40 netmask 255.255.255.0
#ifconfig tunnel46 up
最后,声明隧道两端点的ipv6地址,其中setaddr是文件夹里边的另外一个函数,参数分别是目的ipv6地址和本机ipv6地址。
#./setaddr 2001:da8:bf::1234:5678:9 2001:da8:bf::1234:1234:2