Linux下多媒体业务差分IPv6测试平台的设计与实现
时间:08-02
来源:互联网
点击:
Linux可加载内核模块编程
测试平台使用Linux可加载内核模块(Loadable KernelModule, LKM)来实现差分QoS调度。模块(Module)是内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但是其代码可以在运行时链接到系统中作为内核的一部分运行或从内核取下,动态扩展内核的功能。动态可加载内核模块的目标代码一旦链接到内核,作用和静态链接的内核目标代码完全等价。
每个LKM至少由两个基本的函数组成,一个是用于初始化所有的数据的函数init_module ( ) ,一个是用于清除数据从而能安全地退出的函数cleanup_module ( ) 。为了在模块中使用Netfitler的钩子函数,需要在初始化函数中调用nf_register_hook ( ) 函数注册Netfiter Hook, 在清除函数中调用nf _unregister_hook ( )函数注销Netfiter Hook。具体过程如下:
/ /定义并填充用于注册函数的数据结构
static struct nf_hook_op s post_route = {
{NULL, NULL},
DiffSev_post_route, / /处理函数
PF_ INET6, / /使用IPv6协议NF_ IP6_POST_ROUTING,
/ /使用IPv6的第一个Hook
NF_ IP6_PR I_F IRST,
/ /让自己的函数首先执行
};
/ /初始化程序
int init_module ()
{**
nf_register_hook (&post_route) ;
/ /注册Netfiter Hook
return 0;
}
/ /清除程序
void cleanup_module ()
{
**
nf_unregister_hook (&post_route) ;
/ /注销Netfiter Hook
return;
}
注册钩子函数后,需要编写处理函数,对截获的数据包进行处理。模块获取数据包后,判断其优先级,然后根据放入不同的队列,进行业务差分的调度,保证实时业务的服务质量。模块在完成对数据包的操作之后,可以返回下列预定义的Netfiter返回之中的一个。
其中,最为常用的为前三个返回值。NF_DROP的含义是该数据包将被完全丢弃,所有为它分配的资源都应当被释放。NF_ACCEP返回值告诉Netfilter到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络堆栈的下一个阶段。NF_STOLEN告诉Netfilter“忘掉”这个数据包。这里告诉Netfilter的是:该hook函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是hook函数从Netfilter获取了该数据包的所有权。
程序中对数据判断时,首先有一个对SIP服务器数据的处理,模块对截获数据包的源地址和目的地址进行检查,只要是发往和来自SIP的数据都将被无条件返回,返回值为NF_ACCEPT。这样用作会话连接建立服务器的数据被看作是网络信令数据,获得绝对的高优先级,保证了不同主机之间可以随时建立连接。为了简化操作,这里我们只比较IPv6地址的最后32位来判断。以下为数据包处理函数片断:
unsigned intVowlan_post_route (unsigned int hooknum, struct sk_buff
3 3 skb, const struct net_device 3 in, const struct net_device 3
out, int (3 okfn) ( struct sk_buff 3 ) )
{
struct ipv6hdr 3 ipv6h = (3 skb) - > nh. ipv6h;
struct in6_addr saddr = ipv6h - > saddr;
struct in6_addr daddr = ipv6h - > daddr;
int p rio = addr_belong(daddr) ;
/ /SIP服务器数据,不进行处理,直接返回,具有绝对高优先级
if ( saddr. s6_addr32 [3 ] = = 0x11010000) return NF_ACCEPT;
if (daddr. s6_addr32 [3 ] = = 0x11010000) return NF_ACCEPT;
**/ /区分QoS, 将数据插入不同的队列
switch (p rio) {
case H IGH_PR IOR ITY: {
sendbuffer_insert(3 skb, H IGH_PR IOR ITY) ;
/ /加入高优先级队列
return NF_STOLEN;
}
case LOW_PR IOR ITY: {
sendbuffer_insert (3 skb, LOW_PR IOR ITY) ;
/ /加入低优先级队列
return NF_STOLEN; }
return NF_ACCEPT;
}
被加入不同优先级队列的数据包将被按照上一节中提到的调度算法被转发,因为本文旨在介绍开放式的试验平台,所以具体调度算法的程序实现不再赘述。
编译内核模块,将生成的DiffServ. o作为一个内核模块插入系统,此模块可以象其他系统模块一样进行后台运行。当内核模块不再需要时,可以使用命令将其卸载。相应命令分别如下:
insmod DiffServ. o / /加载内核模块
rmmod DiffServ / /卸载内核模块
测试平台使用Linux可加载内核模块(Loadable KernelModule, LKM)来实现差分QoS调度。模块(Module)是内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但是其代码可以在运行时链接到系统中作为内核的一部分运行或从内核取下,动态扩展内核的功能。动态可加载内核模块的目标代码一旦链接到内核,作用和静态链接的内核目标代码完全等价。
每个LKM至少由两个基本的函数组成,一个是用于初始化所有的数据的函数init_module ( ) ,一个是用于清除数据从而能安全地退出的函数cleanup_module ( ) 。为了在模块中使用Netfitler的钩子函数,需要在初始化函数中调用nf_register_hook ( ) 函数注册Netfiter Hook, 在清除函数中调用nf _unregister_hook ( )函数注销Netfiter Hook。具体过程如下:
/ /定义并填充用于注册函数的数据结构
static struct nf_hook_op s post_route = {
{NULL, NULL},
DiffSev_post_route, / /处理函数
PF_ INET6, / /使用IPv6协议NF_ IP6_POST_ROUTING,
/ /使用IPv6的第一个Hook
NF_ IP6_PR I_F IRST,
/ /让自己的函数首先执行
};
/ /初始化程序
int init_module ()
{**
nf_register_hook (&post_route) ;
/ /注册Netfiter Hook
return 0;
}
/ /清除程序
void cleanup_module ()
{
**
nf_unregister_hook (&post_route) ;
/ /注销Netfiter Hook
return;
}
注册钩子函数后,需要编写处理函数,对截获的数据包进行处理。模块获取数据包后,判断其优先级,然后根据放入不同的队列,进行业务差分的调度,保证实时业务的服务质量。模块在完成对数据包的操作之后,可以返回下列预定义的Netfiter返回之中的一个。
其中,最为常用的为前三个返回值。NF_DROP的含义是该数据包将被完全丢弃,所有为它分配的资源都应当被释放。NF_ACCEP返回值告诉Netfilter到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络堆栈的下一个阶段。NF_STOLEN告诉Netfilter“忘掉”这个数据包。这里告诉Netfilter的是:该hook函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是hook函数从Netfilter获取了该数据包的所有权。
程序中对数据判断时,首先有一个对SIP服务器数据的处理,模块对截获数据包的源地址和目的地址进行检查,只要是发往和来自SIP的数据都将被无条件返回,返回值为NF_ACCEPT。这样用作会话连接建立服务器的数据被看作是网络信令数据,获得绝对的高优先级,保证了不同主机之间可以随时建立连接。为了简化操作,这里我们只比较IPv6地址的最后32位来判断。以下为数据包处理函数片断:
unsigned intVowlan_post_route (unsigned int hooknum, struct sk_buff
3 3 skb, const struct net_device 3 in, const struct net_device 3
out, int (3 okfn) ( struct sk_buff 3 ) )
{
struct ipv6hdr 3 ipv6h = (3 skb) - > nh. ipv6h;
struct in6_addr saddr = ipv6h - > saddr;
struct in6_addr daddr = ipv6h - > daddr;
int p rio = addr_belong(daddr) ;
/ /SIP服务器数据,不进行处理,直接返回,具有绝对高优先级
if ( saddr. s6_addr32 [3 ] = = 0x11010000) return NF_ACCEPT;
if (daddr. s6_addr32 [3 ] = = 0x11010000) return NF_ACCEPT;
**/ /区分QoS, 将数据插入不同的队列
switch (p rio) {
case H IGH_PR IOR ITY: {
sendbuffer_insert(3 skb, H IGH_PR IOR ITY) ;
/ /加入高优先级队列
return NF_STOLEN;
}
case LOW_PR IOR ITY: {
sendbuffer_insert (3 skb, LOW_PR IOR ITY) ;
/ /加入低优先级队列
return NF_STOLEN; }
return NF_ACCEPT;
}
被加入不同优先级队列的数据包将被按照上一节中提到的调度算法被转发,因为本文旨在介绍开放式的试验平台,所以具体调度算法的程序实现不再赘述。
编译内核模块,将生成的DiffServ. o作为一个内核模块插入系统,此模块可以象其他系统模块一样进行后台运行。当内核模块不再需要时,可以使用命令将其卸载。相应命令分别如下:
insmod DiffServ. o / /加载内核模块
rmmod DiffServ / /卸载内核模块
- 一种基于OPNET的小型网络仿真及分析(04-08)
- APOX软件在A+B频段无线网络规划中的应用(06-26)
- 基于GUI的跳频OFDM系统仿真设计(03-03)
- 基于CPLD的RS-232串口通信实现(04-23)
- 2.5 Gbps收发器中1∶2解复用电路的设计(09-17)
- 填补网络 SoC 设计前端与后端验证的差距(09-19)