wintun: Move exchange buffer in separate struct on heap
This allows buffer alignment and keeps it together with its meta-data. Furthermore, the write buffer has been reduced - as long as we flush after _every_ write, we don't need a 1MiB write buffer. Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
		
							parent
							
								
									4863089120
								
							
						
					
					
						commit
						6581cfb885
					
				
					 1 changed files with 44 additions and 33 deletions
				
			
		|  | @ -18,7 +18,8 @@ const ( | |||
| 	packetSizeMax           uint32 = 0xeffc   // Maximum packet size: 4 + packetSizeMax == 0xf000
 | ||||
| 	packetExchangeMax       uint32 = 256      // Number of packets that may be written at a time
 | ||||
| 	packetExchangeAlignment uint32 = 16       // Number of bytes packets are aligned to in exchange buffers
 | ||||
| 	packetExchangeSize      uint32 = 0x100000 // Exchange buffer size (defaults to 1MiB)
 | ||||
| 	packetExchangeSizeRead  uint32 = 0x100000 // Read exchange buffer size (defaults to 1MiB)
 | ||||
| 	packetExchangeSizeWrite uint32 = 0x10000  // Write exchange buffer size (defaults to 64kiB)
 | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
|  | @ -28,18 +29,26 @@ const ( | |||
| 	signalMax | ||||
| ) | ||||
| 
 | ||||
| type exchgBufRead struct { | ||||
| 	data   [packetExchangeSizeRead]byte | ||||
| 	offset uint32 | ||||
| 	avail  uint32 | ||||
| } | ||||
| 
 | ||||
| type exchgBufWrite struct { | ||||
| 	data      [packetExchangeSizeWrite]byte | ||||
| 	offset    uint32 | ||||
| 	packetNum uint32 | ||||
| } | ||||
| 
 | ||||
| type nativeTun struct { | ||||
| 	wt         *wintun.Wintun | ||||
| 	tunName    string | ||||
| 	signalName *uint16 | ||||
| 	tunFile    *os.File | ||||
| 	wrBuff      [packetExchangeSize]byte | ||||
| 	rdBuff      [packetExchangeSize]byte | ||||
| 	rdBuff     *exchgBufRead | ||||
| 	wrBuff     *exchgBufWrite | ||||
| 	signals    [signalMax]windows.Handle | ||||
| 	wrOffset    uint32 | ||||
| 	wrPacketNum uint32 | ||||
| 	rdOffset    uint32 | ||||
| 	rdAvailabe  uint32 | ||||
| 	events     chan TUNEvent | ||||
| 	errors     chan error | ||||
| } | ||||
|  | @ -88,6 +97,8 @@ func CreateTUN(ifname string) (TUNDevice, error) { | |||
| 		wt:         wt, | ||||
| 		tunName:    wt.DataFileName(), | ||||
| 		signalName: signalNameUTF16, | ||||
| 		rdBuff:     &exchgBufRead{}, | ||||
| 		wrBuff:     &exchgBufWrite{}, | ||||
| 		events:     make(chan TUNEvent, 10), | ||||
| 		errors:     make(chan error, 1), | ||||
| 	} | ||||
|  | @ -203,19 +214,19 @@ func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | |||
| 	} | ||||
| 
 | ||||
| 	for { | ||||
| 		if tun.rdOffset+4 <= tun.rdAvailabe { | ||||
| 			// Get packet from the queue.
 | ||||
| 			size := *(*uint32)(unsafe.Pointer(&tun.rdBuff[tun.rdOffset])) | ||||
| 		if tun.rdBuff.offset+4 <= tun.rdBuff.avail { | ||||
| 			// Get packet from the exchange buffer.
 | ||||
| 			size := *(*uint32)(unsafe.Pointer(&tun.rdBuff.data[tun.rdBuff.offset])) | ||||
| 			pSize := packetAlign(4 + size) | ||||
| 			if packetSizeMax < size || tun.rdAvailabe < tun.rdOffset+pSize { | ||||
| 			if packetSizeMax < size || tun.rdBuff.avail < tun.rdBuff.offset+pSize { | ||||
| 				// Invalid packet size.
 | ||||
| 				tun.rdAvailabe = 0 | ||||
| 				tun.rdBuff.avail = 0 | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| 			// Copy data.
 | ||||
| 			copy(buff[offset:], (*(*[packetSizeMax]byte)(unsafe.Pointer(&tun.rdBuff[tun.rdOffset+4])))[:size]) | ||||
| 			tun.rdOffset += pSize | ||||
| 			copy(buff[offset:], (*(*[packetSizeMax]byte)(unsafe.Pointer(&tun.rdBuff.data[tun.rdBuff.offset+4])))[:size]) | ||||
| 			tun.rdBuff.offset += pSize | ||||
| 			return int(size), nil | ||||
| 		} | ||||
| 
 | ||||
|  | @ -249,16 +260,16 @@ func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | |||
| 		} | ||||
| 
 | ||||
| 		// Fill queue.
 | ||||
| 		n, err := tun.tunFile.Read(tun.rdBuff[:]) | ||||
| 		n, err := tun.tunFile.Read(tun.rdBuff.data[:]) | ||||
| 		if err != nil { | ||||
| 			// TUN interface stopped, returned incomplete data, etc.
 | ||||
| 			// Retry.
 | ||||
| 			tun.rdAvailabe = 0 | ||||
| 			tun.rdBuff.avail = 0 | ||||
| 			tun.closeTUN() | ||||
| 			continue | ||||
| 		} | ||||
| 		tun.rdOffset = 0 | ||||
| 		tun.rdAvailabe = uint32(n) | ||||
| 		tun.rdBuff.offset = 0 | ||||
| 		tun.rdBuff.avail = uint32(n) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -266,9 +277,9 @@ func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { | |||
| 
 | ||||
| func (tun *nativeTun) flush() error { | ||||
| 	// Flush write buffer.
 | ||||
| 	_, err := tun.tunFile.Write(tun.wrBuff[:tun.wrOffset]) | ||||
| 	tun.wrPacketNum = 0 | ||||
| 	tun.wrOffset = 0 | ||||
| 	_, err := tun.tunFile.Write(tun.wrBuff.data[:tun.wrBuff.offset]) | ||||
| 	tun.wrBuff.packetNum = 0 | ||||
| 	tun.wrBuff.offset = 0 | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -286,7 +297,7 @@ func (tun *nativeTun) putTunPacket(buff []byte) error { | |||
| 	} | ||||
| 	pSize := packetAlign(4 + size) | ||||
| 
 | ||||
| 	if tun.wrPacketNum >= packetExchangeMax || tun.wrOffset+pSize >= packetExchangeSize { | ||||
| 	if tun.wrBuff.packetNum >= packetExchangeMax || tun.wrBuff.offset+pSize >= packetExchangeSizeWrite { | ||||
| 		// Exchange buffer is full -> flush first.
 | ||||
| 		err := tun.flush() | ||||
| 		if err != nil { | ||||
|  | @ -295,11 +306,11 @@ func (tun *nativeTun) putTunPacket(buff []byte) error { | |||
| 	} | ||||
| 
 | ||||
| 	// Write packet to the exchange buffer.
 | ||||
| 	*(*uint32)(unsafe.Pointer(&tun.wrBuff[tun.wrOffset])) = size | ||||
| 	copy((*(*[packetSizeMax]byte)(unsafe.Pointer(&tun.wrBuff[tun.wrOffset+4])))[:size], buff) | ||||
| 	*(*uint32)(unsafe.Pointer(&tun.wrBuff.data[tun.wrBuff.offset])) = size | ||||
| 	copy((*(*[packetSizeMax]byte)(unsafe.Pointer(&tun.wrBuff.data[tun.wrBuff.offset+4])))[:size], buff) | ||||
| 
 | ||||
| 	tun.wrPacketNum++ | ||||
| 	tun.wrOffset += pSize | ||||
| 	tun.wrBuff.packetNum++ | ||||
| 	tun.wrBuff.offset += pSize | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue