0

我们已经为电力线通信开发了一个 ASIC,并且正在为此开发一个以太网设备驱动程序。该芯片通过串行外设接口连接到我们的主处理器(iMX233 ARM9)。我们开发的内核模块在加载时注册了一个以太网设备“gvspi”。接收时。我们通过 SPI 从 ASIC 获取以太网帧并将其存储在一个字节数组中,然后分配一个 sk_buff,将数组中的数据处理到这个 sk_buff 并将其传递给 TCP/IP 层。在传输过程中,我们通过 SPI 将以太网帧(通过 sk_buff->data 检索到的字节数组)发送到 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 的帧没有被 TCP/IP 层处理。会是这样吗?我们是否在将 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;
}
4

1 回答 1

0

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

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

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

于 2013-04-16T09:30:37.077 回答