当前位置: 技术问答>linux和unix
修改数据帧头的问题
来源: 互联网 发布时间:2016-04-04
本文导语: 您好,我刚刚接触Linux网络驱动方面,对驱动的各部分有了总体认识,但是有些细节不是很了解。 目前有以下几个问题: 1.看到网卡驱动中有skb buffer和ring buffer两种缓冲区。请问两个有什么区别,分别存放什么,...
您好,我刚刚接触Linux网络驱动方面,对驱动的各部分有了总体认识,但是有些细节不是很了解。
目前有以下几个问题:
1.看到网卡驱动中有skb buffer和ring buffer两种缓冲区。请问两个有什么区别,分别存放什么,
这两个缓冲区分别是在哪里申请的阿,比如说skb是在内存的物理映射区,那ring buffer呢?
2.TX_ring_size和RX_ring_size以及MIN_MTU和MAX_MTU的值是怎么确定的?一个数据包的大小不是
46-1500字节吗?还有skb大小怎么定?缓冲区里可以容纳多少个数据包一次?
3.netif_rx将数据包传给上层协议,这个过程是怎么进行的阿?是需要传给一个系统接口然后再传给
应用程序吗?那能不能让netif_rx直接把数据包传给应用程序阿?我们有个应用想通过驱动直接获取
并处理数据包,而不经过系统接口。
4.在网卡驱动中,我想在数据发送前将目的MAC地址修改成想要的地址,这样的做法可行吗?即:
在hard_start_xmit函数的开始处添加代码: memcpy(eth->h_dest, change->daddr, dev->addr_len);
其中change_addr是我自己定义的。
5.在数据接收时我想提前修改目的MAC地址和源MAC地址,那么我在net_rx函数的开头添加代码:
memcpy(eth->h_source, change->saddr, dev->addr_len);
memcpy(eth->h_dest, change->daddr, dev->addr_len);
这样能实现吗,可行吗?
目前有以下几个问题:
1.看到网卡驱动中有skb buffer和ring buffer两种缓冲区。请问两个有什么区别,分别存放什么,
这两个缓冲区分别是在哪里申请的阿,比如说skb是在内存的物理映射区,那ring buffer呢?
2.TX_ring_size和RX_ring_size以及MIN_MTU和MAX_MTU的值是怎么确定的?一个数据包的大小不是
46-1500字节吗?还有skb大小怎么定?缓冲区里可以容纳多少个数据包一次?
3.netif_rx将数据包传给上层协议,这个过程是怎么进行的阿?是需要传给一个系统接口然后再传给
应用程序吗?那能不能让netif_rx直接把数据包传给应用程序阿?我们有个应用想通过驱动直接获取
并处理数据包,而不经过系统接口。
4.在网卡驱动中,我想在数据发送前将目的MAC地址修改成想要的地址,这样的做法可行吗?即:
在hard_start_xmit函数的开始处添加代码: memcpy(eth->h_dest, change->daddr, dev->addr_len);
其中change_addr是我自己定义的。
5.在数据接收时我想提前修改目的MAC地址和源MAC地址,那么我在net_rx函数的开头添加代码:
memcpy(eth->h_source, change->saddr, dev->addr_len);
memcpy(eth->h_dest, change->daddr, dev->addr_len);
这样能实现吗,可行吗?
|
看你的意思,可能想做一个二层的协议吧,你如果想将二层报文直接送到用户空间,可以尝试使用
linux的SOCK_PACKET或者Raw Socket。
SOCK_PACKET is linux specific way of getting packets at the dev level.
环形队列是用在“轮询”收包技术中的,是一个包含sk_buff的双向循环列表,是用于DMA内存映射的。
1、首先,内核在主内存中为收发数据建立一个环形的缓冲队列(通常叫DMA环形缓冲区)。
2、内核将这个缓冲区通过DMA映射,把这个队列交给网卡;
3、网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;
4、内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;[/color]
上述过程代码可以参考函数e100_rx_alloc_list与e100_rx_clean。
至于"中断"收包方式,中断收到skbuff的报文,netif_rx把报文入到队列input_pkt_queue中,然后又调用netif_rx_schedule把伪设备backlog_dev放入poll list队列,并触发软中断NET_RX_SOFTIRQ。软中断调用伪设备的poll函数process_backlog,process_backlog函数把报文出队列input_pkt_queue。交给上层(比如IP、ARP)处理。
所以如果想在收包以后修改报文的SMAC和DMAC,建议在netif_receive_skb函数中做修改。
如果想在发包的时候修改DMAC,建议在dev_queue_xmit函数中做修改。
因为这两个函数都是和网卡硬件无关的。再往下就和硬件相关了。
linux的SOCK_PACKET或者Raw Socket。
SOCK_PACKET is linux specific way of getting packets at the dev level.
环形队列是用在“轮询”收包技术中的,是一个包含sk_buff的双向循环列表,是用于DMA内存映射的。
1、首先,内核在主内存中为收发数据建立一个环形的缓冲队列(通常叫DMA环形缓冲区)。
2、内核将这个缓冲区通过DMA映射,把这个队列交给网卡;
3、网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;
4、内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;[/color]
上述过程代码可以参考函数e100_rx_alloc_list与e100_rx_clean。
至于"中断"收包方式,中断收到skbuff的报文,netif_rx把报文入到队列input_pkt_queue中,然后又调用netif_rx_schedule把伪设备backlog_dev放入poll list队列,并触发软中断NET_RX_SOFTIRQ。软中断调用伪设备的poll函数process_backlog,process_backlog函数把报文出队列input_pkt_queue。交给上层(比如IP、ARP)处理。
所以如果想在收包以后修改报文的SMAC和DMAC,建议在netif_receive_skb函数中做修改。
如果想在发包的时候修改DMAC,建议在dev_queue_xmit函数中做修改。
因为这两个函数都是和网卡硬件无关的。再往下就和硬件相关了。
|
哈,点名提问呀,本人交斗胆先回答了
1 sk_buff是Linux内核中维护数据包数据用的,它的使用贯穿整个协议栈,sk_buff在接收到数据包的时候会被创建.而你说的ring buffer责是驱动自己维护的一个接收或者发送数据的缓冲,这些空间一般是在驱动启动的时候分配的.
2 TX/RX_ring_size是驱动定义的东西,它根据自己硬件特性定义的,在协议栈中并没有MIN_MTU和MAX_MTU的概念,只有MTU的概念,个人猜测它应该是这个设备的MTU可以被设置的一个范围吧.sk_buff的大小无论在接收的时候还是发送的时候都是知道数据包的大小的,只有这个2个时候创建sk_buff.
不知道你说的这个缓冲区是指的哪个的缓冲区,一般来说网络设备的队列是1024,不过可以在驱动中设定,这个缓冲是问题3中要问答的
3 netif_rx会把sk_buff放入一个缓冲队列中,然后发出一个软中断,这个软中断用于处理sk_buff,这时就是进入了我们的协议栈了
可以,不过不建议这么作,如果你需要可以注册一个对协议ETH_P_ALL的处理函数,那么你的这个函数就可以处理所有的数据包,至于怎么写,这个说了就太多了
不通过系统接口,这不是个好主意,只能这个提议,因为不知道你们具体的需求.
4 可以,只是兼容性问题,如果换了别的网卡呢?
5 net_rx是什么?我暂且把它当作是你要打netif_rx吧,这个也是可以的
4和5合起来说吧,只要确定好eth就没问题.
希望不是太难看懂
1 sk_buff是Linux内核中维护数据包数据用的,它的使用贯穿整个协议栈,sk_buff在接收到数据包的时候会被创建.而你说的ring buffer责是驱动自己维护的一个接收或者发送数据的缓冲,这些空间一般是在驱动启动的时候分配的.
2 TX/RX_ring_size是驱动定义的东西,它根据自己硬件特性定义的,在协议栈中并没有MIN_MTU和MAX_MTU的概念,只有MTU的概念,个人猜测它应该是这个设备的MTU可以被设置的一个范围吧.sk_buff的大小无论在接收的时候还是发送的时候都是知道数据包的大小的,只有这个2个时候创建sk_buff.
不知道你说的这个缓冲区是指的哪个的缓冲区,一般来说网络设备的队列是1024,不过可以在驱动中设定,这个缓冲是问题3中要问答的
3 netif_rx会把sk_buff放入一个缓冲队列中,然后发出一个软中断,这个软中断用于处理sk_buff,这时就是进入了我们的协议栈了
可以,不过不建议这么作,如果你需要可以注册一个对协议ETH_P_ALL的处理函数,那么你的这个函数就可以处理所有的数据包,至于怎么写,这个说了就太多了
不通过系统接口,这不是个好主意,只能这个提议,因为不知道你们具体的需求.
4 可以,只是兼容性问题,如果换了别的网卡呢?
5 net_rx是什么?我暂且把它当作是你要打netif_rx吧,这个也是可以的
4和5合起来说吧,只要确定好eth就没问题.
希望不是太难看懂
|
建议在软中断后的函数内改;
4:在dev_queue_xmit后改更合适,需要考虑arp报文问题.
5:很别扭,做实验就罢了.
4:在dev_queue_xmit后改更合适,需要考虑arp报文问题.
5:很别扭,做实验就罢了.
|
3.传递给应用程序,可不可以这样做呢?先通过读取PP_RxLength获取数据长度,然后读取到一个由kmalloc申请的缓冲区中,接着使用copy_to_user()拷贝到用户区。
1楼的,他那个net_rx可能是一个数据接收子程序吧,中断的时候调用的,里面使用了netif_rx(skb);
1楼的,他那个net_rx可能是一个数据接收子程序吧,中断的时候调用的,里面使用了netif_rx(skb);
|
2 楼的说的清楚