阅读:2120回复:0
从一块网卡接收的数据直接交给另一块网卡发送如何实现
我的机器有两块网卡,操作系统为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; } |
|