最近开发了一个新协议,在开发的过程中出现了,网卡收到一个包,协议解析后却给协议栈送了两个skb,导致设备一直重包问题,经过几天的调试才定位道问题。
新协议的开发,基本上是添加自己需要的报文头,然后再解析还原原始的报文。
这里收包的地方采用:
定义新的struct packet_type 结构体,然后插入到内核队列
static struct packet_type new_packet_type __read_mostly = {
#ifdef NEW_PACKET_TYPE_ALL
.type = cpu_to_be16(ETH_P_ALL),
#else
.type = cpu_to_be16(NEW_PROTO_TYPE),
#endif
.func = new_procol_rcv,
};
在new_procol_rcv函数中添加自的报文头解析流程和去头操作,然后丢回协议栈。
在丢回协议栈的时候出现了问题,那就是netif_receive_skb(skb);的使用问题。
如果使用.type = cpu_to_be16(NEW_PROTO_TYPE),的话截获报文的插入点在二层报文处理的最后,自然要使用netif_receive_skb来重新丢带协议栈,但是使用.type = cpu_to_be16(ETH_P_ALL),的话,报文截获的插入点,在二层报文处理的开头,经过测试,如果使用netif_receive_skb,有的接口就会出现重包现象,如果不使用netif_receive_skb有的接口就无法向协议栈推送报文,经过对比测试发现,如果是正常的eth口需要使用netif_receive_skb才能正常向协议栈推送报文,,如果eth口是桥的从接口,使用netif_receive_skb后就会重包,不使用netif_receive_skb就正常了。至此修改报文的推送方式如下:
if(!(skb->dev->priv_flags & IFF_BRIDGE_PORT))
{
netif_receive_skb(skb);
}
测试设备,再也没有出现重包现象。