TCP不适用于自定义网络设备驱动程序

时间:2013-04-10 11:53:40

标签: linux-kernel linux-device-driver kernel-module

我们已开发出用于电力线通信的ASIC,并正在开发用于此的以太网设备驱动程序。该芯片通过串行外设接口连接到我们的主处理器(iMX233 ARM9)。我们开发的内核模块在加载时注册了一个以太网设备“gvspi”。在接收时。我们通过SPI从ASIC获取以太网帧并将其存储在字节数组中,然后分配一个sk_buff,将来自数组的数据处理到此sk_buff并将其传递给TCP / IP层。在传输过程中,我们通过SPI将以太网帧(通过sk_buff->数据检索的字节数组)发送到ASIC,然后ASIC将其发送到电力线上。

我们有这样的设置:

ARM Board1 --SPI - > ASIC ---电源线---> ASIC --SPI - > ARM Board2

两个运行Linux内核版本2.6.31的ARM板

我们可以使用我们的驱动程序相互ping(使用ping)ARM板。 我们能够在ARM板之间双向交换UDP数据包(使用iperf)。 但是我们无法在两块板之间建立TCP连接(使用telnet / telnetd或iperf)。

似乎TCP / IP层没有处理包含TCP的唯一帧。可能是这种情况吗?我们是否在将sk_buff传递给上层之前正确填充它?

以下是驱动程序代码的相应部分,它创建,填充并将sk_buff传递给上层(u32 rx_data和u8 rx_len存储刚收到的以太网帧):

skb1 = alloc_skb((rx_len + NET_IP_ALIGN), GFP_ATOMIC);
skb_reserve(skb1, NET_IP_ALIGN);
skb_put(skb1, rx_len);
memcpy(skb1->data, rx_data, rx_len );               
skb1->protocol = eth_type_trans(skb1,gvspi_dev);
skb_reset_network_header(skb1);
skb_reset_transport_header(skb1);

gvspi_dev->stats.rx_bytes += skb1->len;
gvspi_dev->stats.rx_packets++; 

printk("Frame sent to TCP/IP layer...");

if (netif_rx_ni (skb1) != NET_RX_SUCCESS) {
    kfree_skb (skb1);
    gvspi_dev->stats.rx_dropped++;      
    return ERROR;
}

1 个答案:

答案 0 :(得分:0)

所以我们能够找出问题 - RTFM类别问题。 我们已将自定义以太网驱动程序的MAC地址分配为11:22:33:44:55:66,这当然是多播地址(参见图here

对于那些想要细节的人: 查看内核源代码的tcp_ipv4.c中tcp_v4_rcv()的行号1615

每当我们使用多播MAC地址时,发送到此TCPv4接收功能的sk_buff都会从较低层预设PACKET_MULTICAST。 因此,此时sk_buff被拒绝了,因为收到的帧并没有按照TCP的要求专门定向到我们的主机。组播仅在UDP等无连接协议中有效。