I want to report an issue I found with your example (send ring buffer get corrupted)

Oded Katz <[email protected]> Fri, 23 Jan 2026 11:34:17 -0800
Newsgroups com.zx2c4.lists.wireguard
Message-ID <CAApnxP0OicCUvxYo41sK8AnK=bxqR+qE2BTxFmE5cJbSyOJrBQ@mail.gmail.com>
Hi,we were trying to integrate `wintun` into our product and while
testing we found an issue with upload of high UDP throughput on
multiple sockets. initially we thought it may be related to our
integration. but we managed to find the same issue in your example
code.we tried to do some debugging on the example, but it seems like
the corruption is on the driver side.
the way to reproduce this issue- run the example
- run the `send_udp.py` (the attached python script) on 2 different
command terminals
   - `send_udp.py 10.6.7.8 5201 1450`
   - `send_udp.py 10.6.7.8 5201 1400`after some time the
`WintunReceivePacket` returns NULL and `GetLastError()` return 13
(`ERROR_INVALID_DATA`)
many thank,
and I hope you can help us.
btw: in the meantime, I'll try to see if I can contribute myself with a fix
Oded
send_udp.py (text/x-python-script, 5 KB)
#!/usr/bin/env python3

"""
A Python script to send a continuous stream of UDP packets to a specified
host and port.

It prints the number of packets sent every second.

The first 4 bytes of the payload contain a packet counter (little-endian).
The remaining 60 bytes are filled with the character 'a'.

Usage:
    python send_udp_flood.py <address> <port>

Example:
    python send_udp_flood.py 127.0.0.1 8080
"""

import socket
import argparse
import sys
import time

def main():
    # --- 1. Set up the command-line argument parser ---
    parser = argparse.ArgumentParser(
        description="Send a continuous UDP packet stream.",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="Example:\n  python send_udp_flood.py 127.0.0.1 8080"
    )
    
    parser.add_argument("address", 
                        help="The destination IP address or hostname (e.g., 127.0.0.1)")
    
    parser.add_argument("port", 
                        type=int, 
                        help="The destination port (e.g., 8080)")

    parser.add_argument("len", 
                        type=int, 
                        help="The padding len (e.g., 60-1350)")
    
    args = parser.parse_args()

    # --- 2. Create the packet data (padding) ---
    # We create the 60-byte padding once, as it never changes.
    payload_padding = (b'a' * args.len)
    destination = (args.address, args.port)
    
    print(f"Target:     {args.address}:{args.port}")
    print(f"Payload:    {args.len + 4} bytes (4-byte counter + {args.len} 'a's)")
    print("---------------------------------")
    
    # 
    print(f"Starting continuous send. Press Ctrl+C to stop.")

    # Statistics counters
    packets_in_interval = 0
    total_packets_sent = 0 # This will be our packet counter
    
    # Use time.monotonic() for stable time interval measurements
    start_time = time.monotonic()
    last_print_time = start_time

    try:
        # Create a UDP socket
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            
            # --- 3. Main Send Loop ---
            while True:
                
                # --- Create the payload for *this* packet ---
                # Convert the counter to 4 bytes, little-endian
                counter_bytes = total_packets_sent.to_bytes(4, 'little')
                
                # Combine the counter and the padding
                payload_bytes = payload_padding + counter_bytes
                
                # Send the packet
                s.sendto(payload_bytes, destination)
                
                # Increment counters
                packets_in_interval += 1
                total_packets_sent += 1

                # --- 4. Statistics Loop ---
                current_time = time.monotonic()
                elapsed_since_last = current_time - last_print_time

                # Check if 1.0 second has passed
                if elapsed_since_last >= 1.0:
                    # Calculate the rate for this interval
                    rate = packets_in_interval / elapsed_since_last
                    
                    # Print stats (pps = packets per second)
                    # We use f-strings with :>10, to right-align the packet count
                    # and :,.0f to format the rate with commas and no decimals.
                    print(f"Sent {packets_in_interval:>10,} packets. (Rate: {rate:,.0f} pps, {(packets_in_interval * (args.len + 4 + 28) * 8 / 1000 / 1000):,.3f} Mbit/sec)")
                    
                    # Reset for the next interval
                    packets_in_interval = 0
                    last_print_time = current_time
    
    except KeyboardInterrupt:
        # --- 5. Handle Ctrl+C ---
        print("\n---------------------------------")
        print("Stopping...")
        
        # Print final summary statistics
        end_time = time.monotonic()
        total_time = end_time - start_time
        
        if total_time > 0:
            avg_rate = total_packets_sent / total_time
            print(f"Sent a total of {total_packets_sent:n} packets in {total_time:.2f} seconds.")
            print(f"Average rate: {avg_rate:,.0f} pps, {(avg_rate * (args.len + 4 + 28) * 8 / 1000 / 1000):,.3f} Mbit/sec")
                    
        else:
            print("Sent 0 packets.")
        sys.exit(0)
        
    except socket.gaierror as e:
        print(f"\nError: Hostname '{args.address}' could not be resolved.", file=sys.stderr)
        print(f"Details: {e}", file=sys.stderr)
        sys.exit(1)
    except (socket.error, OSError) as e:
        print(f"\nError: Could not send packet.", file=sys.stderr)
        print(f"Details: {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"\nAn unexpected error occurred:", file=sys.stderr)
        print(f"Details: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()