| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package tun
- import (
- "context"
- "errors"
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/header"
- "gvisor.dev/gvisor/pkg/tcpip/stack"
- )
- var ErrQueueEmpty = errors.New("queue is empty")
- type GVisorDevice interface {
- WritePacket(packet *stack.PacketBuffer) tcpip.Error
- ReadPacket() (byte, *stack.PacketBuffer, error)
- Wait()
- }
- // LinkEndpoint implements GVisor stack.LinkEndpoint
- var _ stack.LinkEndpoint = (*LinkEndpoint)(nil)
- type LinkEndpoint struct {
- deviceMTU uint32
- device GVisorDevice
- dispatcherCancel context.CancelFunc
- }
- func (e *LinkEndpoint) MTU() uint32 {
- return e.deviceMTU
- }
- func (e *LinkEndpoint) SetMTU(_ uint32) {
- // not Implemented, as it is not expected GVisor will be asking tun device to be modified
- }
- func (e *LinkEndpoint) MaxHeaderLength() uint16 {
- return 0
- }
- func (e *LinkEndpoint) LinkAddress() tcpip.LinkAddress {
- return ""
- }
- func (e *LinkEndpoint) SetLinkAddress(_ tcpip.LinkAddress) {
- // not Implemented, as it is not expected GVisor will be asking tun device to be modified
- }
- func (e *LinkEndpoint) Capabilities() stack.LinkEndpointCapabilities {
- return stack.CapabilityRXChecksumOffload
- }
- func (e *LinkEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
- if e.dispatcherCancel != nil {
- e.dispatcherCancel()
- e.dispatcherCancel = nil
- }
- if dispatcher != nil {
- ctx, cancel := context.WithCancel(context.Background())
- go e.dispatchLoop(ctx, dispatcher)
- e.dispatcherCancel = cancel
- }
- }
- func (e *LinkEndpoint) IsAttached() bool {
- return e.dispatcherCancel != nil
- }
- func (e *LinkEndpoint) Wait() {
- }
- func (e *LinkEndpoint) ARPHardwareType() header.ARPHardwareType {
- return header.ARPHardwareNone
- }
- func (e *LinkEndpoint) AddHeader(buffer *stack.PacketBuffer) {
- // tun interface doesn't have link layer header, it will be added by the OS
- }
- func (e *LinkEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
- return true
- }
- func (e *LinkEndpoint) Close() {
- if e.dispatcherCancel != nil {
- e.dispatcherCancel()
- e.dispatcherCancel = nil
- }
- }
- func (e *LinkEndpoint) SetOnCloseAction(_ func()) {
- }
- func (e *LinkEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
- var n int
- var err tcpip.Error
- for _, packetBuffer := range packetBufferList.AsSlice() {
- err = e.device.WritePacket(packetBuffer)
- if err != nil {
- return n, &tcpip.ErrAborted{}
- }
- n++
- }
- return n, nil
- }
- func (e *LinkEndpoint) dispatchLoop(ctx context.Context, dispatcher stack.NetworkDispatcher) {
- var networkProtocolNumber tcpip.NetworkProtocolNumber
- var version byte
- var packet *stack.PacketBuffer
- var err error
- for {
- select {
- case <-ctx.Done():
- return
- default:
- version, packet, err = e.device.ReadPacket()
- // on "queue empty", ask device to yield slightly and continue
- if errors.Is(err, ErrQueueEmpty) {
- e.device.Wait()
- continue
- }
- // stop dispatcher loop on any other interface failure
- if err != nil {
- e.Attach(nil)
- return
- }
- // extract network protocol number from the packet first byte
- // (which is returned separately, since it is so incredibly hard to extract one byte from
- // stack.PacketBuffer without additional memory allocation and full copying it back and forth)
- switch version {
- case 4:
- networkProtocolNumber = header.IPv4ProtocolNumber
- case 6:
- networkProtocolNumber = header.IPv6ProtocolNumber
- default:
- // discard unknown network protocol packet
- packet.DecRef()
- continue
- }
- // dispatch the buffer to the stack
- dispatcher.DeliverNetworkPacket(networkProtocolNumber, packet)
- // signal the buffer that it can be released
- packet.DecRef()
- }
- }
- }
|