shangoo
驱动牛犊
驱动牛犊
  • 注册日期2004-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2084回复:0

从一块网卡接收的数据直接交给另一块网卡发送如何实现

楼主#
更多 发布于:2005-01-14 21:25
我的机器有两块网卡,操作系统为Linux,网卡驱动为8139too
我想要做的是:
从网卡1接收的数据,不交给系统,直接交给网卡2进行发送,应该如何实现?

特别是如下两个问题:
1、如何获得网卡2的net_device指针?
2、如何在网卡1的接收中断处理函数中将数据传给网卡2进行发送?

附8139too的接收终端处理函数和发送函数:
static void rtl8139_rx_interrupt (struct net_device *dev,
 struct rtl8139_private *tp, void *ioaddr)
{
unsigned char *rx_ring;
u16 cur_rx;

assert (dev != NULL);
assert (tp != NULL);
assert (ioaddr != NULL);

rx_ring = tp->rx_ring;
cur_rx = tp->cur_rx;

DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
" free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
RTL_R16 (RxBufAddr),
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));

while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
int ring_offset = cur_rx % RX_BUF_LEN;
u32 rx_status;
unsigned int rx_size;
unsigned int pkt_size;
struct sk_buff *skb;

rmb();

/* read size+status of next frame from DMA ring buffer */
rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
rx_size = rx_status >> 16;
pkt_size = rx_size - 4;

DPRINTK ("%s:  rtl8139_rx() status %4.4x, size %4.4x,"
" cur %4.4x.\n", dev->name, rx_status,
rx_size, cur_rx);
#if RTL8139_DEBUG > 2
{
int i;
DPRINTK ("%s: Frame contents ", dev->name);
for (i = 0; i < 70; i++)
printk (" %2.2x",
rx_ring[ring_offset + i]);
printk (".\n");
}
#endif

/* Packet copy from FIFO still in progress.
* Theoretically, this should never happen
* since EarlyRx is disabled.
*/
if (rx_size == 0xfff0) {
tp->xstats.early_rx++;
break;
}

/* If Rx err or invalid rx_size/rx_status received
* (which happens if we get lost in the ring),
* Rx process gets reset, so we abort any further
* Rx processing.
*/
if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
   (rx_size < 8) ||
   (!(rx_status & RxStatusOK))) {
rtl8139_rx_err (rx_status, dev, tp, ioaddr);
return;
}

/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */

/* TODO: consider allocating skb's outside of
* interrupt context, both to speed interrupt processing,
* and also to reduce the chances of having to
* drop packets here under memory pressure.
*/

skb = dev_alloc_skb (pkt_size + 2);
if (skb) {
skb->dev = dev;
skb_reserve (skb, 2); /* 16 byte align the IP fields. */

eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
skb_put (skb, pkt_size);

skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
} else {
printk (KERN_WARNING
"%s: Memory squeeze, dropping packet.\n",
dev->name);
tp->stats.rx_dropped++;
}

cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
RTL_W16 (RxBufPtr, cur_rx - 16);

if (RTL_R16 (IntrStatus) & RxAckBits)
RTL_W16_F (IntrStatus, RxAckBits);
}

DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
" free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
RTL_R16 (RxBufAddr),
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));

tp->cur_rx = cur_rx;
}

static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct rtl8139_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
unsigned int entry;
unsigned int len = skb->len;

/* Calculate the next Tx descriptor entry. */
entry = tp->cur_tx % NUM_TX_DESC;

if (likely(len < TX_BUF_SIZE)) {
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
dev_kfree_skb(skb);
} else {
dev_kfree_skb(skb);
tp->stats.tx_dropped++;
return 0;
}

/* Note: the chip doesn't have auto-pad! */
spin_lock_irq(&tp->lock);
RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
  tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));

dev->trans_start = jiffies;

tp->cur_tx++;
wmb();

if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
spin_unlock_irq(&tp->lock);

DPRINTK ("%s: Queued Tx packet size %u to slot %d.\n",
dev->name, len, entry);

return 0;
}

游客

返回顶部