# MasterDnsVPN Packet Packing and Batch Processing Internals: How Control Packets Are Bundled

> Explore MasterDnsVPN's packet packing and batch processing internals. Learn how it bundles control packets into single datagrams to reduce UDP overhead and efficiently process data.

- Repository: [Amin Mahmoudi/MasterDnsVPN](https://github.com/masterking32/MasterDnsVPN)
- Tags: internals
- Published: 2026-05-10

---

**MasterDnsVPN reduces UDP overhead by concatenating multiple control packets into a single `PACKET_PACKED_CONTROL_BLOCKS` datagram, processing each 7-byte block individually on the receiving end.**

MasterDnsVPN implements an efficient packet packing mechanism that bundles multiple small control packets into a single UDP datagram. This optimization targets the inherent inefficiency of sending individual acknowledgments and control messages, significantly reducing bandwidth consumption and per-packet processing overhead according to the `masterking32/MasterDnsVPN` source code.

## Why Pack Control Packets?

Control packets in MasterDnsVPN carry **no payload**—they include ACK/NACK confirmations, stream-control messages, and DNS acknowledgments. Sending each of these small messages individually wastes bandwidth and increases per-packet latency. By concatenating their metadata into fixed-size blocks, the protocol transmits up to dozens of acknowledgments in a single UDP packet.

The packing mechanism centers on the special packet type **`PACKET_PACKED_CONTROL_BLOCKS`** (value `0x13`), defined in [`internal/enums/packet_identity.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/enums/packet_identity.go). This packet type carries a payload consisting of one or more packed 7-byte blocks containing the original packet metadata.

## Core Data Structures and Constants

The packing system relies on several key constants and structures defined across the `internal/vpnproto` package:

- **`PackedControlBlockSize`**: Fixed at **7 bytes**, defined in [`internal/vpnproto/packing.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/packing.go). Each block contains the packet type, stream ID, sequence number, fragment ID, and total fragments.
- **`PACKET_PACKED_CONTROL_BLOCKS`**: The packet type constant (`0x13`) that identifies packed control payloads.
- **`BuildOptions`**: Parameters used by [`internal/vpnproto/builder.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/builder.go) to assemble raw VPN packets with headers and optional payloads.
- **`maxPackedBlocks`**: Runtime limit calculated by `CalculateMaxPackedBlocks` in [`internal/vpnproto/utils.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/utils.go), determining how many blocks fit within the configured MTU.

## Client-Side Packet Packing Implementation

The client-side packing logic resides primarily in [`internal/client/dispatcher.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/client/dispatcher.go), where the dispatcher coordinates packet transmission.

### Identifying Packable Packets

Before packing, the system determines if a packet qualifies for aggregation. The function `vpnproto.IsPackableControlPacket(pktType, payloadLen)` in [`internal/vpnproto/packing.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/packing.go) returns `true` only for specific control types:

- ACK/NACK packets
- SOCKS5 control messages
- DNS acknowledgments

Packets with payloads or non-control types are excluded from the packing process.

### Collecting and Serializing Blocks

The dispatcher iterates over the selected stream's TX queue (and optionally other streams and the orphan queue), pulling packable control packets until `maxPackedBlocks` is reached. Each block is serialized using `AppendPackedControlBlock`:

```go
payload = VpnProto.AppendPackedControlBlock(payload,
    item.PacketType, selectedStreamID,
    item.SequenceNum, item.FragmentID, item.TotalFragments)

```

This function appends exactly 7 bytes per block to the payload buffer.

### Building the Final Datagram

If multiple blocks are collected, the dispatcher sets the outer packet type to `PACKET_PACKED_CONTROL_BLOCKS` and clears stream-specific fields. The packet is then constructed using `vpnproto.BuildOptions` and passed to the transmission planner. Single packets are transmitted normally without the packing wrapper.

## Server-Side Batch Processing and Unpacking

### Receiving Packed Blocks

When a `PACKET_PACKED_CONTROL_BLOCKS` packet arrives, [`internal/udpserver/server_postsession.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/server_postsession.go) routes it to `handlePackedControlBlocksRequest`. This handler uses `ForEachPackedControlBlock` to iterate through the payload:

```go
VpnProto.ForEachPackedControlBlock(vpnPacket.Payload, func(packetType uint8,
    streamID uint16, sequenceNum uint16, fragmentID uint8, totalFragments uint8) bool {
    
    block := VpnProto.Packet{
        SessionID:       vpnPacket.SessionID,
        SessionCookie:   vpnPacket.SessionCookie,
        PacketType:      packetType,
        StreamID:        streamID,
        HasStreamID:     true,
        SequenceNum:     sequenceNum,
        HasSequenceNum:  true,
        FragmentID:      fragmentID,
        TotalFragments:  totalFragments,
    }
    // Process inner packet...
    return true
})

```

`ForEachPackedControlBlock` walks the payload 7 bytes at a time, invoking the callback for each block.

### Individual Block Processing

Each unpacked block is processed as a standard inbound packet through `preprocessInboundPacket` (for duplicate detection) and `dispatchPostSessionPacket` (for routing to ACK or stream-control handlers). **Nested packing is not supported**—if a packed block contains another `PACKET_PACKED_CONTROL_BLOCKS` type, it is ignored.

### Creating Server-Side Batches

The server builds packed packets in [`internal/udpserver/server_session.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/server_session.go) via the `packControlBlocks` function:

1. Start with the first control packet and append additional blocks from active streams or the orphan queue
2. Respect the `record.MaxPackedBlocks` limit to avoid fragmentation
3. Use `AppendPackedControlBlock` to serialize each component
4. Set the final packet type to `PACKET_PACKED_CONTROL_BLOCKS`

## Maximum Block Calculations and MTU Constraints

The function `CalculateMaxPackedBlocks` in [`internal/vpnproto/utils.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/utils.go) determines the optimal number of blocks per packet:

```go
effectiveSize := (mtu * percent) / 100
count := max(min(max(effectiveSize / vpnproto.PackedControlBlockSize, 1), absoluteMax), 1)

```

This calculation ensures packed packets fit comfortably within the MTU while maximizing density. The client initializes `c.maxPackedBlocks` using this function when creating a new `Client` instance.

## Reliability and Duplicate Transmission

Both client and server optionally repeat packed blocks to improve reliability over unreliable UDP transport. The server stores the last packed block in `record.LastPackedControlBlock` with a counter `LastPackedControlBlockRemaining`, governed by the `PacketBlockControlDuplication` configuration. The client tracks retransmission counts via `runtimePacketDuplicationCount` to prevent excessive duplication while maintaining delivery guarantees.

## Summary

- **7-byte blocks**: Each control packet packs into a fixed-size block containing type, stream ID, sequence number, and fragment metadata.
- **Type 0x13**: `PACKET_PACKED_CONTROL_BLOCKS` identifies aggregated control packets.
- **Client aggregation**: [`client/dispatcher.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/client/dispatcher.go) collects packable packets using `IsPackableControlPacket` and `AppendPackedControlBlock`.
- **Server unpacking**: [`server_postsession.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/server_postsession.go) uses `ForEachPackedControlBlock` to iterate and process individual blocks.
- **MTU awareness**: `CalculateMaxPackedBlocks` ensures optimal packing density without fragmentation.
- **Nested protection**: The protocol explicitly ignores nested packed packets to prevent parsing errors.

## Frequently Asked Questions

### What is the size of each packed control block?

Each packed control block is exactly **7 bytes**, defined as the constant `PackedControlBlockSize` in [`internal/vpnproto/packing.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/packing.go). This compact size includes the packet type, stream ID, sequence number, fragment ID, and total fragments count, allowing efficient aggregation of multiple control messages.

### How does MasterDnsVPN prevent nested packing?

The server explicitly checks for and ignores any packed blocks that contain the `PACKET_PACKED_CONTROL_BLOCKS` type (0x13). This protection, implemented in `handlePackedControlBlocksRequest` within [`internal/udpserver/server_postsession.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/udpserver/server_postsession.go), ensures that the unpacking process only processes one level of aggregation and avoids recursive parsing complexity.

### What happens if the packed packet would exceed the MTU?

The `CalculateMaxPackedBlocks` function in [`internal/vpnproto/utils.go`](https://github.com/masterking32/MasterDnsVPN/blob/main/internal/vpnproto/utils.go) pre-calculates the maximum number of 7-byte blocks that fit within a percentage of the MTU. Both client and server respect this limit (`maxPackedBlocks` or `record.MaxPackedBlocks`), ensuring packed payloads never exceed safe transmission sizes and preventing IP fragmentation.

### Can packed packets contain data payloads or only control packets?

Packed packets **only contain control packets**. The `IsPackableControlPacket` function explicitly checks that the payload length is zero and the packet type is a recognized control type (ACK, NACK, SOCKS5 control, etc.). Data packets with actual payloads are transmitted separately and are never bundled into `PACKET_PACKED_CONTROL_BLOCKS` datagrams.