原始以太网广播

发布于 2024-11-18 16:06:34 字数 286 浏览 2 评论 0原文

我下载了 WinDDK 并使用 ndisprot 5x 从我的用户应用程序广播原始以太网数据包,指定目标 MAC 全部为 0xff,在大型且重复的数据集上,它似乎效率不高。

目前效果很好的是环回 - 将目标和源 MAC 指定为我自己的,我获得了所需的速度,但数据包永远不会离开我的网卡。

也许我缺少一些 ndis 驱动程序选项并等待广播使用此示例 MS 驱动程序完成?我想要的只是将数据包广播到网络,我并不真正关心传送状态,并希望尽快摆脱它。

一个只有 2 点的系统在这里会有帮助吗?我不确定是什么导致了滞后。

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.

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.

Maybe I am missing some ndis driver options and wait for a broadcast to complete using this sample MS driver? 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? I am not sure what is causing a lag.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

江挽川 2024-11-25 16:06:34

在内核模式下不可能消除发送完成路径。原因是网卡正忙于从内存中读取字节,直到它最终发出发送完成信号。如果您在重新使用数据包之前没有等待发送完成,那么网卡将没有机会读取完整的数据包。您最终会发送损坏的数据。

但是,您说得对,使用库存 NDISPROT 示例发送大量数据时效率非常低。问题在于 NDISPROT 的用户模式示例应用程序同步将数据写入内核模式。这意味着您的线程开始写入(发送数据包),然后阻塞,直到写入(发送数据包)完成。 (该示例效率低下,因为 NDISPROT 示例的目的是说明如何在内核模式下与 NDIS 进行互操作,而不是说明用户内核通信的复杂技术。)

您可以通过使用以下几种技术之一来大大加快速度 :同时处理多条数据:

  1. 使用多线程。执行与现在相同的操作,只不过在多个线程上并行执行。这很容易设置,但扩展性不太好(要扩展至 10 倍流量,您需要 10 倍线程,然后您就会开始因缓存问题而受到伤害)。另外,如果您的数据集必须按顺序发送,则需要一堆复杂的同步来确保线程按顺序发出请求。

  2. 对 WriteFile 和 OVERLAPPED 数据结构使用异步调用。这需要您对用户模式应用程序进行一些重组。 (幸运的是,您不需要接触内核驱动程序,因为它已经支持这一点)。通过重叠写入,您可以从单个线程同时发出多个写入,然后在其中任何一个(或全部)完成时收到通知。如果您对重叠设计足够仔细,您应该能够轻松填充 100Mbps 网络链接。

更明确地说,这就是您当前所拥有的:

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

如您所见,在网卡将数据包有效负载从 RAM 复制到 NIC 硬件的整个过程中,您的用户模式应用程序一直停留在 WriteFile 中。相反,如果您使用异步写入内核模式,您将得到以下结果:

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

在此设置中,WriteFile 返回得更快,因此您有机会排队另一个数据包(或 10 个),同时NIC 仍在读取第一个数据包。您可以使用任何常用的重叠技术来确定写入(发送数据包)何时完成,并且可以重用数据缓冲区。

要开始使用异步 I/O,请从 开始本文档。 (哎呀,看起来他们的图表与我很棒的 ASCII 艺术旋转了 90°...)。

It's not possible to eliminate the send-completion path in kernel mode. The reason is that the network card is busy reading bytes from memory, until it finally issues a send-completion. 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. The problem is that the NDISPROT's usermode sample application writes data to kernelmode synchronously. 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.)

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). 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. 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). With OVERLAPPED writes, you can issue multiple simultaneous writes from a single thread, then get notified when any (or all) of them completes. If you're sufficiently careful with the overlapped design, you should be able to fill a 100Mbps network link easily.

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. 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. 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.

To get started with asynchronous I/O, start with this documentation. (Oops, looks like their diagrams are rotated 90° from my awesome ASCII-art...).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文