vproxy-tools / Divert-Java

Java binding for WinDivert using panama-native-interface
MIT License
2 stars 0 forks source link

WinDivertRcvSndCtx required while sending packet. #2

Open aichemzee opened 2 months ago

aichemzee commented 2 months ago

Hi I'm trying to read a lot of packets to a queue and then sending them one by one based on certain conditions / modifications.

However we do require a context while sending the packet. What would be the best way to achieve this?

  1. Should I create a new context for each recv call? This would preserve the context for sending but this would generate a lot of garbage.

  2. Or should I re use the same context for all send / receive calls. Would this cause problems? Since I'll have a few consumer threads for reading and a separate one for dispatching.

wkgcass commented 2 months ago

The ctx is simply a helper for reusing intermediate variables required by the C library.
The most improtant thing to know is that the buf is reused and rewrote everytime you call receive functions, and the returned MemorySegment of the received packet is a slice of the buf.
So each ctx should be bond to one sending||receiving thread.
Furthermore, if you need to pass the packet to somewhere else, you will have to copy the memory of the packet.

In your case, you will need to:

  1. receive the packet
  2. clone the packet: newSeg.copyFrom(seg)
  3. store the packet into a queue
  4. pop from the queue, and manipulate it
  5. send the packet
aichemzee commented 1 month ago

Let's see scenario 1:

  1. I have one central queue.
  2. I have X threads that are reading from DLL and pushing data to the queue.
  3. I have Y threads that are reading from the queue and performing some manipulation then re injecting the data into DLL.

Questions:

  1. Can I have a separate RecvSend Context for each of the above threads (i.e. total X+Y contexts).
  2. Would I need to retain the context that was used to receive this packet for injecting?

Let's see scenario 2:

  1. I have X threads, each thread has a context. Each threads receives a packet from DLL, performs some manipulation then re injects that packet back into the dll.

Which of the two scenarios would you recommend?

wkgcass commented 1 month ago

I would recommend scenario 2, the model would be much simpler, and performance would be better since the buffers could be reused.

For scenario 1:

  1. Yes, you will need X+Y ctx.
  2. No, the ctx info is not required, but the packet must be cloned before leaving the thread (i.e. pushing into the queue).

Also please note that the driver copies each packet to all matched windivert handles, so you would have to manually distribute packets to each threads.
Currently windivert does not support bitwise operators, so you would have to use tcp.DstPort > 0 and tcp.DstPort < 32768, which would not be easy to evenly distribute the packets.

It would be much more simple to use and more performant if windivert could support bitwise operators or hash functions.
See also: https://github.com/basil00/Divert/issues/265

wkgcass commented 1 month ago

Maybe some PRs would be helpful, however I believe windivert is not meant for high performance packet processing, but a convenient tool for some lightweight network handling.
You would need dpdk if you want to process packets on an enterprise level workload.