简体   繁体   English

原始以太网广播

[英]Raw ethernet broadcasting

I downloaded WinDDK and am using ndisprot 5x to broadcast raw ethernet packets from my user app, specifying destination MAC all 0xff's, on large and repetitive data sets it doesn't seem to be very productive.我下载了 WinDDK 并使用 ndisprot 5x 从我的用户应用程序广播原始以太网数据包,将目标 MAC 全部指定为 0xff,在大型且重复的数据集上,它似乎不是很有效率。

What currently works great is a loopback - specifying destination and source MAC's as my own I get needed speed, but the packet never leaves my network card.目前最有效的是环回 - 将目标和源 MAC 指定为我自己的我获得所需的速度,但数据包永远不会离开我的网卡。

Maybe I am missing some ndis driver options and wait for a broadcast to complete using this sample MS driver?也许我错过了一些 ndis 驱动程序选项并等待使用此示例 MS 驱动程序完成广播? All I want is the packet to be broadcasted to network and I don't really care about the delivery status and want to get rid of it as fast as possible.我想要的只是将数据包广播到网络,我并不真正关心交付状态并希望尽快摆脱它。

Would a system having only 2 points help here?只有 2 分的系统在这里有帮助吗? I am not sure what is causing a lag.我不确定是什么导致了延迟。

It's not possible to eliminate the send-completion path in kernel mode.在 kernel 模式下无法消除发送完成路径。 The reason is that the network card is busy reading bytes from memory, until it finally issues a send-completion.原因是网卡忙于从 memory 读取字节,直到它最终发出发送完成。 If you didn't wait for send-completion before re-using the packet, then the network card wouldn't have had an opportunity to read the full packet.如果您在重新使用数据包之前没有等待发送完成,那么网卡将没有机会读取完整的数据包。 You'd end up sending corrupted data.您最终会发送损坏的数据。

But, you're right that there is a big inefficiency when using the stock NDISPROT sample to send huge quantities of data.但是,您是对的,当使用库存 NDISPROT 样本发送大量数据时效率非常低。 The problem is that the NDISPROT's usermode sample application writes data to kernelmode synchronously .问题是 NDISPROT 的用户模式示例应用程序将数据同步写入内核模式。 That means that your thread begins a write (send packet), then blocks until the write (send packet) completes.这意味着您的线程开始写入(发送数据包),然后阻塞直到写入(发送数据包)完成。 (The sample is inefficient, because the point of the NDISPROT sample is to illustrate how to interoperate with NDIS in kernelmode, not to illustrate complicated techniques for user-kernel communication.) (该示例效率低下,因为 NDISPROT 示例的目的是说明如何在内核模式下与 NDIS 进行互操作,而不是说明用户与内核通信的复杂技术。)

You can vastly speed this up by using one of several techniques to issue multiple pieces of data simultaneously:您可以通过使用多种技术中的一种同时发布多条数据来大大加快速度:

  1. Use multithreading.使用多线程。 Do the same thing you're doing now, except do it on multiple threads in parallel.做你现在正在做的同样的事情,除了在多个线程上并行执行。 This is pretty easy to set up, but it doesn't scale very well (to scale up to 10x traffic, you need 10x threads, and then you start to get hurt on caching issues).这很容易设置,但扩展性不是很好(要扩展至 10 倍流量,您需要 10 倍线程,然后您开始在缓存问题上受到伤害)。 Plus, if your dataset must be sent in order, you need a bunch of complicated synchronization to make sure the threads issue requests in order.另外,如果你的数据集必须按顺序发送,你需要一堆复杂的同步来确保线程按顺序发出请求。

  2. Use asynchronous calls with WriteFile and OVERLAPPED data structures.对 WriteFile 和 OVERLAPPED 数据结构使用异步调用。 This requires you to do some retooling on the usermode app.这需要您对用户模式应用程序进行一些改造。 (Fortunately you don't need to touch the kernel driver, since that already supports this). (幸运的是,您不需要触摸 kernel 驱动程序,因为它已经支持这个)。 With OVERLAPPED writes, you can issue multiple simultaneous writes from a single thread, then get notified when any (or all) of them completes.使用 OVERLAPPED 写入,您可以从单个线程发出多个同时写入,然后在其中任何(或全部)完成时收到通知。 If you're sufficiently careful with the overlapped design, you should be able to fill a 100Mbps network link easily.如果您对重叠设计足够小心,您应该能够轻松填充 100Mbps 网络链接。

To be more explicit, this is what you currently have today:更明确地说,这是您目前拥有的:

Your app           NDISPROT driver         Network card         The network
---------------------------------------------------------------------------------
  WriteFile
   .      \-------> NdisProtWrite
   .                            \-------> NdisSendPackets
   .                                            |
   .                                   (copy packet payload
   .                                    from system RAM to
   .                                    network card's buffer)
   .                                            |
   .                                            |---------------> Start sending
   .             NdisProtSendComplete <---------|                      .
  WriteFile <----/                              |                      .
   returns                                      |<--------------- Finish sending

As you can see, your usermode app is stuck in WriteFile the entire time that the network card copies the packet payload from RAM to the NIC hardware.如您所见,在网卡将数据包有效负载从 RAM 复制到 NIC 硬件的整个过程中,您的用户模式应用程序一直停留在 WriteFile 中。 Instead, if you use asynchronous writes to kernelmode, you'll wind up with this:相反,如果您对内核模式使用异步写入,您将得到以下结果:

Your app           NDISPROT driver         Network card         The network
---------------------------------------------------------------------------------
  WriteFile
   .      \-------> NdisProtWrite
   .               |            \-------> NdisSendPackets
  WriteFile <------/                           |
   returns                              (copy packet payload
                                        from system RAM to
                                        network card's buffer)
                                                |
                                                |---------------> Start sending
                 NdisProtSendComplete <---------|                      .
  Async write <--/                              |                      .
   completes                                    |<--------------- Finish sending

In this setup, WriteFile returns more quickly, and so you have a chance to queue up another packet (or 10) while the NIC is still reading the first packet.在此设置中,WriteFile 返回更快,因此您有机会在 NIC 仍在读取第一个数据包时排队另一个数据包(或 10 个)。 You can use any of the usual OVERLAPPED techniques to determine when the write (send packet) has completed, and you can reuse the data buffer.您可以使用任何常用的 OVERLAPPED 技术来确定写入(发送数据包)何时完成,并且您可以重用数据缓冲区。

To get started with asynchronous I/O, start with this documentation .要开始使用异步 I/O,请从本文档开始。 (Oops, looks like their diagrams are rotated 90° from my awesome ASCII-art...). (哎呀,看起来他们的图表从我很棒的 ASCII-art 旋转了 90°...)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM