Hi,
I am developing a simple passthrough proxy system extension using NETransparentProxyProvider. This is what the extension fundamentally does:
- In handleNewFlow open a connection to the remote endpoint using CreateTCPConnection method in Tunnel provider.
- Once the remote endpoint is connected open the NEAppProxyTCPFlow and start both ends of the flow.
When I use perf to test the network speed while sending I see a 10 times drop in speed when using my system extension.
iperf -c <server_address>
iperf uses 131072 byte blocks to send data by default for 10 seconds
My code for inbound and outbound flows is quite simple:
For inbound flow read from the remote connection, in the completion handler for read write to the flow and in the completion handler for flow start another read from remote.
For outbound flow read from the flow, in the completion handler write to the remote and in the completion handler for writing to the remote trigger another read from the flow.
Is there any problem with the above approach which can cause network transfer slowdown?
I also captured Wireshark traces for cases with and without my system extension and I see a pattern there.
When I read from the flow the system extension reads chunks of varying sizes irrespective of what the application is sending. Eg. I see 4096, 16384, 8192. When I send these chunks to the remote connection it keeps waiting for ACKs for each chunk irrespective of the TCP window size. I also see a [PSH, ACK] in the last packet for each chunk.
Without my system extension, iperf sends many packets in short time without [PSH,ACK] as it is using bigger buffer and does not wait for ACKs so frequently. It respects the TCP window size.
I can provide any details needed to help root cause this problem. I am testing this on macOS BigSur 11.5.1
Any help is greatly appreciated
Regards