我们已开发出用于电力线通信的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;
}
答案 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等无连接协议中有效。