当前位置:Linux教程 - Linux - linux kernel2.4里面接收数据分组的过程和体会

linux kernel2.4里面接收数据分组的过程和体会

文章提要:linux kernel2.4里面接收数据分组的过程和体会

luster

最近一个科研项目的需要,在linux 下面写了一些代码。其中要涉及到接收处理一个特殊的分组。这个分组的头部(IPv6+UDP)由于某种需要而被压缩改变了。我的代码要完成的工作之一就是根据某些信息恢复出原始的头标。如何接收这个分组呢?

一个想法就是,发送分组的时候把以太祯的类型设置为IPv6,这样内核接收到该分组后,会提交给ip6_rcv(),然后我们在ip6_rcv()函数的开始处,嵌入自己的代码进行头标的恢复。但是这样做总感觉不是很好,我的想法是完成一个相对独立的LKM,而不需要修改内核的源代码。

经过分析发现,内核处理接收数据的流程是,网卡驱动把接收到的数据组织好,然后提取以太祯中的协议类型域,然后填写skb,最后调用netif_rx()把这个skb 放到内核接收队列里面。然后系统在自己的软中断中通过net_rx_action()查看这个skb 队列,如果有数据就提取出来,根据skb->protocol来调用相应的处理函数,例如如果是IPV6的话,就调用ip6_rcv(). ip6_rcv()就是整个内核中IPv6协议的一个入口点。

经过这个分析后,我采用了如下的方法来实现我前面的需求。我在内核里面注册了一种新的分组协议和该协议的对应的接收处理函数。这样,当内核接收到我所关心的特殊分组后,在net_rx_action里面就会寻找到我这个对应的接收处理函数。我在处理函数里面对IPv6+UDP头部进行恢复。然后如何提交给ip6入口点呢?呵呵,我这里采用的是将skb->protocol 域置为 IPv6,然后再次调用netif_rx(),把分组放到接收队列里面。这样在下一个软中断到来的时候,我们修改恢复后的IPv6分组就可以被正常接收了。:))

这里在实际编程中发现,如果在我的接收函数里面,如果直接修改内核调用传入的skb,然后把这个skb再次放到netif_rx()调用后的队列里面,会不时出现kernel panic 。后来我采用的是先skb_clone一个sk_buff,然后对这个新buff操作,并将这个新buff放到队列里面,而在我的接受函数里面是把这个原来的skb free掉。现在是OK了。:))

由于我正在自己的机器上进一步测试我的代码,现在无聊,就来这里发了这篇帖子,
也算是一种处理方法把。不知道这个处理方法是否非常OLD :):)


Luster
2002/6/8