github.com/google/netstack@v0.0.0-20191123085552-55fcc16cd0eb/tcpip/link/channel/channel.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package channel provides the implemention of channel-based data-link layer
    16  // endpoints. Such endpoints allow injection of inbound packets and store
    17  // outbound packets in a channel.
    18  package channel
    19  
    20  import (
    21  	"github.com/google/netstack/tcpip"
    22  	"github.com/google/netstack/tcpip/buffer"
    23  	"github.com/google/netstack/tcpip/stack"
    24  )
    25  
    26  // PacketInfo holds all the information about an outbound packet.
    27  type PacketInfo struct {
    28  	Pkt   tcpip.PacketBuffer
    29  	Proto tcpip.NetworkProtocolNumber
    30  	GSO   *stack.GSO
    31  }
    32  
    33  // Endpoint is link layer endpoint that stores outbound packets in a channel
    34  // and allows injection of inbound packets.
    35  type Endpoint struct {
    36  	dispatcher stack.NetworkDispatcher
    37  	mtu        uint32
    38  	linkAddr   tcpip.LinkAddress
    39  	GSO        bool
    40  
    41  	// C is where outbound packets are queued.
    42  	C chan PacketInfo
    43  }
    44  
    45  // New creates a new channel endpoint.
    46  func New(size int, mtu uint32, linkAddr tcpip.LinkAddress) *Endpoint {
    47  	return &Endpoint{
    48  		C:        make(chan PacketInfo, size),
    49  		mtu:      mtu,
    50  		linkAddr: linkAddr,
    51  	}
    52  }
    53  
    54  // Drain removes all outbound packets from the channel and counts them.
    55  func (e *Endpoint) Drain() int {
    56  	c := 0
    57  	for {
    58  		select {
    59  		case <-e.C:
    60  			c++
    61  		default:
    62  			return c
    63  		}
    64  	}
    65  }
    66  
    67  // InjectInbound injects an inbound packet.
    68  func (e *Endpoint) InjectInbound(protocol tcpip.NetworkProtocolNumber, pkt tcpip.PacketBuffer) {
    69  	e.InjectLinkAddr(protocol, "", pkt)
    70  }
    71  
    72  // InjectLinkAddr injects an inbound packet with a remote link address.
    73  func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remote tcpip.LinkAddress, pkt tcpip.PacketBuffer) {
    74  	e.dispatcher.DeliverNetworkPacket(e, remote, "" /* local */, protocol, pkt)
    75  }
    76  
    77  // Attach saves the stack network-layer dispatcher for use later when packets
    78  // are injected.
    79  func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
    80  	e.dispatcher = dispatcher
    81  }
    82  
    83  // IsAttached implements stack.LinkEndpoint.IsAttached.
    84  func (e *Endpoint) IsAttached() bool {
    85  	return e.dispatcher != nil
    86  }
    87  
    88  // MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
    89  // during construction.
    90  func (e *Endpoint) MTU() uint32 {
    91  	return e.mtu
    92  }
    93  
    94  // Capabilities implements stack.LinkEndpoint.Capabilities.
    95  func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
    96  	caps := stack.LinkEndpointCapabilities(0)
    97  	if e.GSO {
    98  		caps |= stack.CapabilityHardwareGSO
    99  	}
   100  	return caps
   101  }
   102  
   103  // GSOMaxSize returns the maximum GSO packet size.
   104  func (*Endpoint) GSOMaxSize() uint32 {
   105  	return 1 << 15
   106  }
   107  
   108  // MaxHeaderLength returns the maximum size of the link layer header. Given it
   109  // doesn't have a header, it just returns 0.
   110  func (*Endpoint) MaxHeaderLength() uint16 {
   111  	return 0
   112  }
   113  
   114  // LinkAddress returns the link address of this endpoint.
   115  func (e *Endpoint) LinkAddress() tcpip.LinkAddress {
   116  	return e.linkAddr
   117  }
   118  
   119  // WritePacket stores outbound packets into the channel.
   120  func (e *Endpoint) WritePacket(_ *stack.Route, gso *stack.GSO, protocol tcpip.NetworkProtocolNumber, pkt tcpip.PacketBuffer) *tcpip.Error {
   121  	p := PacketInfo{
   122  		Pkt:   pkt,
   123  		Proto: protocol,
   124  		GSO:   gso,
   125  	}
   126  
   127  	select {
   128  	case e.C <- p:
   129  	default:
   130  	}
   131  
   132  	return nil
   133  }
   134  
   135  // WritePackets stores outbound packets into the channel.
   136  func (e *Endpoint) WritePackets(_ *stack.Route, gso *stack.GSO, hdrs []stack.PacketDescriptor, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) (int, *tcpip.Error) {
   137  	payloadView := payload.ToView()
   138  	n := 0
   139  packetLoop:
   140  	for _, hdr := range hdrs {
   141  		off := hdr.Off
   142  		size := hdr.Size
   143  		p := PacketInfo{
   144  			Pkt: tcpip.PacketBuffer{
   145  				Header: hdr.Hdr,
   146  				Data:   buffer.NewViewFromBytes(payloadView[off : off+size]).ToVectorisedView(),
   147  			},
   148  			Proto: protocol,
   149  			GSO:   gso,
   150  		}
   151  
   152  		select {
   153  		case e.C <- p:
   154  			n++
   155  		default:
   156  			break packetLoop
   157  		}
   158  	}
   159  
   160  	return n, nil
   161  }
   162  
   163  // WriteRawPacket implements stack.LinkEndpoint.WriteRawPacket.
   164  func (e *Endpoint) WriteRawPacket(vv buffer.VectorisedView) *tcpip.Error {
   165  	p := PacketInfo{
   166  		Pkt:   tcpip.PacketBuffer{Data: vv},
   167  		Proto: 0,
   168  		GSO:   nil,
   169  	}
   170  
   171  	select {
   172  	case e.C <- p:
   173  	default:
   174  	}
   175  
   176  	return nil
   177  }
   178  
   179  // Wait implements stack.LinkEndpoint.Wait.
   180  func (*Endpoint) Wait() {}