我们已经为电力线通信开发了一个 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;
}