当前位置: 技术问答>linux和unix
一个网络驱动方面的问题!急,解决就给分!
来源: 互联网 发布时间:2015-09-29
本文导语: 请问各位大侠,网卡收到数据时,是通过函数netif_rx()把sk_buff送到上层的,那么我怎么在执行netif_rx()时,把sk_buff同时送给另一个函数? 我试了一下,在执行netif_rx()时是不可以访问sk_buff的. 请问有什么好的解决办法? ...
请问各位大侠,网卡收到数据时,是通过函数netif_rx()把sk_buff送到上层的,那么我怎么在执行netif_rx()时,把sk_buff同时送给另一个函数?
我试了一下,在执行netif_rx()时是不可以访问sk_buff的.
请问有什么好的解决办法?
接收的函数如下:
static void
e1000_clean_rx_irq(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
struct sk_buff *skb;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
int i;
int msgId;
unsigned char payload[40]; // 16->36 &&&&&&&&&&& ->40 by Qifeng
int len = 40;
int error_code=0;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
while(rx_desc->status & E1000_RXD_STAT_DD) {
pci_unmap_single(pdev,
rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
skb = rx_ring->buffer_info[i].skb;
length = le16_to_cpu(rx_desc->length);
if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
/* All receives must fit into a single buffer */
E1000_DBG("Receive packet consumed multiple buffersn");
dev_kfree_skb_irq(skb);
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
last_byte = *(skb->data + length - 1);
if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
&adapter->stats,
length, skb->data);
spin_unlock_irqrestore(&adapter->stats_lock,
flags);
length--;
} else {
dev_kfree_skb_irq(skb);
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
}
/* Good Receive */
skb_put(skb, length - ETHERNET_FCS_SIZE);
#if (LINUX_VERSION_CODE truesize = skb->len;
#endif
/* Receive Checksum Offload */
e1000_rx_checksum(adapter, rx_desc, skb);
#ifdef IANS
{
iANSsupport_t *ans = adapter->iANSdata;
if(ans->iANS_status == IANS_COMMUNICATION_UP) {
if(bd_ans_os_Receive(adapter, rx_desc, skb) == BD_ANS_FAILURE)
dev_kfree_skb_irq(skb);
else
netif_rx(skb);
} else {
#endif
skb->protocol = eth_type_trans(skb, netdev);
#ifdef NETIF_F_HW_VLAN_TX
if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
} else {
netif_rx(skb);
}
#else
netif_rx(skb);
#endif
#ifdef IANS
}
}
#endif
netdev->last_rx = jiffies;
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
#ifdef MNG
msgId = ioctl_send((struct send_param *)skb);(这边是我加的函数)
#endif
rx_ring->next_to_clean = i;
e1000_alloc_rx_buffers(adapter);
}
我试了一下,在执行netif_rx()时是不可以访问sk_buff的.
请问有什么好的解决办法?
接收的函数如下:
static void
e1000_clean_rx_irq(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
struct e1000_rx_desc *rx_desc;
struct sk_buff *skb;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
int i;
int msgId;
unsigned char payload[40]; // 16->36 &&&&&&&&&&& ->40 by Qifeng
int len = 40;
int error_code=0;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
while(rx_desc->status & E1000_RXD_STAT_DD) {
pci_unmap_single(pdev,
rx_ring->buffer_info[i].dma,
rx_ring->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
skb = rx_ring->buffer_info[i].skb;
length = le16_to_cpu(rx_desc->length);
if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
/* All receives must fit into a single buffer */
E1000_DBG("Receive packet consumed multiple buffersn");
dev_kfree_skb_irq(skb);
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
last_byte = *(skb->data + length - 1);
if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
&adapter->stats,
length, skb->data);
spin_unlock_irqrestore(&adapter->stats_lock,
flags);
length--;
} else {
dev_kfree_skb_irq(skb);
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
continue;
}
}
/* Good Receive */
skb_put(skb, length - ETHERNET_FCS_SIZE);
#if (LINUX_VERSION_CODE truesize = skb->len;
#endif
/* Receive Checksum Offload */
e1000_rx_checksum(adapter, rx_desc, skb);
#ifdef IANS
{
iANSsupport_t *ans = adapter->iANSdata;
if(ans->iANS_status == IANS_COMMUNICATION_UP) {
if(bd_ans_os_Receive(adapter, rx_desc, skb) == BD_ANS_FAILURE)
dev_kfree_skb_irq(skb);
else
netif_rx(skb);
} else {
#endif
skb->protocol = eth_type_trans(skb, netdev);
#ifdef NETIF_F_HW_VLAN_TX
if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
(rx_desc->special & E1000_RXD_SPC_VLAN_MASK));
} else {
netif_rx(skb);
}
#else
netif_rx(skb);
#endif
#ifdef IANS
}
}
#endif
netdev->last_rx = jiffies;
memset(rx_desc, 0, sizeof(struct e1000_rx_desc));
mb();
rx_ring->buffer_info[i].skb = NULL;
i = (i + 1) % rx_ring->count;
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
#ifdef MNG
msgId = ioctl_send((struct send_param *)skb);(这边是我加的函数)
#endif
rx_ring->next_to_clean = i;
e1000_alloc_rx_buffers(adapter);
}
|
那么你在调用netif_rx()之前先使用skb_colone()或者skb_copy()等函数把这个skb备份一份出来再去交给你自己定义的函数不就OK了?