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

Linux kernel TCP不适用于自定义网络设备驱动程序,linux-kernel,linux-device-driver,kernel-module,Linux Kernel,Linux Device Driver,Kernel Module,我们已经开发了用于电力线通信的ASIC,并正在为其开发以太网设备驱动程序。该芯片通过串行外围接口连接到我们的主机处理器(iMX233 ARM9)。我们开发的核心模块在加载时注册一个以太网设备“gvspi”。在接收时。我们通过SPI从ASIC获取以太网帧,并将其存储在字节数组中,然后分配一个sku buff,将数组中的数据处理到此sku buff,并将其传递到TCP/IP层。在传输过程中,我们通过SPI将以太网帧(通过sk_buff->data检索的字节数组)发送到ASIC,然后ASIC将其输出到

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

我们有这样的设置:

ARM板1--SPI-->ASIC--电源线-->ASIC--SPI-->ARM板2

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

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

似乎只有包含TCP的帧没有被TCP/IP层处理。会是这样吗?在将sk_buff传递到上层之前,我们是否正确填充了sk_buff

以下是驱动程序代码的适当部分,用于创建、填充sk_buff并将其传递到上层(u32 rx_数据和u8 rx_len存储刚刚接收到的以太网帧):


因此,我们能够找到问题-RTFM类别问题。 我们已经为自定义以太网驱动程序分配了MAC地址11:22:33:44:55:66,这当然是一个多播地址(见图)

对于那些想要了解详细信息的人: 查看内核源代码的tcp_ipv4.c中tcp_v4_rcv()的行号

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

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;
}