对于一个研究项目,我目前正在修改一个Linux驱动程序。我对这个话题还比较陌生,所以我不确定我在这里犯了一个明显的错误。
我的目标是在驱动程序IRQ期间捕获传入的ICMP数据包,并立即将回复发送回发送方。现在,无论如何,如果校验和或任何事情是正确的,我只想尽快发回一些东西。为此,我在IRQ期间运行以下代码:
data = skb-> data;
/* we received an ICMP request. Send custom reply. */
if(data[9] == 1){// && data[20] == 8){
unsigned long start = jiffies;
unsigned long end;
u8 * newdata;
u16 ippacketLength;
sk_quickreply = dev_alloc_skb(128);
struct ethhdr * mac_skb_quick;
struct iphdr * iph_skb_quick;
struct ethhdr * mac_skb = eth_hdr(skb);
struct iphdr * iph_skb = data;
quicktransmit = 1;
/* Put icmp packet */
skb_push(sk_quickreply, 26);
/* Put IP header */
skb_push(sk_quickreply, sizeof(struct iphdr));
skb_reset_network_header(sk_quickreply);
iph_skb_quick = ip_hdr(sk_quickreply);
iph_skb_quick->version = 4;
iph_skb_quick->ihl = 5;
iph_skb_quick->ttl = 64;
iph_skb_quick->daddr = iph_skb->saddr;
iph_skb_quick->saddr = iph_skb->daddr;
iph_skb_quick->protocol = 1; //ICMP
ip_send_check(iph_skb_quick);
/* Put MAC header */
eth_header(sk_quickreply, dev, ETH_P_802_3, mac_skb->h_source, mac_skb->h_dest, 14);
skb_reset_mac_header(sk_quickreply);
mac_skb_quick = eth_hdr(sk_quickreply);
rtl8168_mystart_xmit(sk_quickreply,dev);
}
其中rtl8168_mystart_xmit是驱动程序最初提供的hard_start_xmit函数,但我删除了自旋锁:
static int rtl8168_mystart_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct rtl8168_private *tp = netdev_priv(dev);
unsigned int frags, entry;
struct TxDesc *txd;
void __iomem *ioaddr = tp->mmio_addr;
dma_addr_t mapping;
u32 len;
u32 opts1;
u32 opts2;
int ret = NETDEV_TX_OK;
unsigned long flags, large_send;
printk(KERN_INFO "Starting transmission of fast reply.\n");
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
if (netif_msg_drv(tp)) {
printk(KERN_ERR
"%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
}
goto err_stop;
}
entry = tp->cur_tx % NUM_TX_DESC;
txd = tp->TxDescArray + entry;
if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
goto err_stop;
opts1 = DescOwn;
opts2 = rtl8168_tx_vlan_tag(tp, skb);
large_send = 0;
if (dev->features & NETIF_F_TSO) {
u32 mss = skb_shinfo(skb)->gso_size;
printk(KERN_INFO "Large send.\n");
/* TCP Segmentation Offload (or TCP Large Send) */
if (mss) {
if ((tp->mcfg == CFG_METHOD_1) ||
(tp->mcfg == CFG_METHOD_2) ||
(tp->mcfg == CFG_METHOD_3)) {
opts1 |= LargeSend | ((mss & MSSMask) << 16);
} else if ((tp->mcfg == CFG_METHOD_11) ||
(tp->mcfg == CFG_METHOD_12) ||
(tp->mcfg == CFG_METHOD_13)) {
opts2 |= LargeSend_DP | ((mss & MSSMask) << 18);
} else {
opts1 |= LargeSend;
opts2 |= (mss & MSSMask) << 18;
}
large_send = 1;
}
}
if (large_send == 0) {
printk(KERN_INFO "No large send.\n");
if (dev->features & NETIF_F_IP_CSUM) {
if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3))
opts1 |= rtl8168_tx_csum(skb, dev);
else
opts2 |= rtl8168_tx_csum(skb, dev);
}
}
frags = rtl8168_xmit_frags(tp, skb, opts1, opts2);
printk(KERN_INFO "Frags: %u\n", frags);
if (frags) {
len = skb_headlen(skb);
opts1 |= FirstFrag;
} else {
len = skb->len;
tp->tx_skb[entry].skb = skb;
if (tp->UseSwPaddingShortPkt && len < 60) {
printk(KERN_INFO "Packet uses padding\n");
rtl8168_sw_padding_short_pkt(tp, skb, opts1, opts2);
opts1 |= FirstFrag;
frags++;
} else {
printk(KERN_INFO "Packet doesn't use padding\n");
//This code means, the fragment is the first and the last fragment to be send
opts1 |= FirstFrag | LastFrag;
}
}
printk(KERN_INFO "Length: %u\n", len);
opts1 |= len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
tp->tx_skb[entry].len = len;
txd->addr = cpu_to_le64(mapping);
txd->opts2 = cpu_to_le32(opts2);
txd->opts1 = cpu_to_le32(opts1&~DescOwn);
wmb();
txd->opts1 = cpu_to_le32(opts1);
dev->trans_start = jiffies;
tp->cur_tx += frags + 1;
wmb();
RTL_W8(TxPoll, HPQ); /* set polling bit */
out:
return ret;
err_stop:
printk(KERN_INFO "Problem: Jumped to err_stop\n");
//netif_stop_queue(dev);
//ret = NETDEV_TX_BUSY;
//RTLDEV->stats.tx_dropped++;
spin_unlock_irqrestore(&tp->lock, flags);
goto out;
}
我正在从第二台计算机发送ping请求,这台计算机已经设置为混杂模式。似乎答案永远不会在第一时间发送。我做错了什么或者甚至可能在IRQ期间传输这样的信息?
提前感谢您的帮助。