github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/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/FlowerWrong/netstack/tcpip" 22 "github.com/FlowerWrong/netstack/tcpip/buffer" 23 "github.com/FlowerWrong/netstack/tcpip/stack" 24 ) 25 26 // PacketInfo holds all the information about an outbound packet. 27 type PacketInfo struct { 28 Header buffer.View 29 Payload buffer.View 30 Proto tcpip.NetworkProtocolNumber 31 GSO *stack.GSO 32 } 33 34 // Endpoint is link layer endpoint that stores outbound packets in a channel 35 // and allows injection of inbound packets. 36 type Endpoint struct { 37 dispatcher stack.NetworkDispatcher 38 mtu uint32 39 linkAddr tcpip.LinkAddress 40 GSO bool 41 42 // C is where outbound packets are queued. 43 C chan PacketInfo 44 } 45 46 // New creates a new channel endpoint. 47 func New(size int, mtu uint32, linkAddr tcpip.LinkAddress) *Endpoint { 48 return &Endpoint{ 49 C: make(chan PacketInfo, size), 50 mtu: mtu, 51 linkAddr: linkAddr, 52 } 53 } 54 55 // Drain removes all outbound packets from the channel and counts them. 56 func (e *Endpoint) Drain() int { 57 c := 0 58 for { 59 select { 60 case <-e.C: 61 c++ 62 default: 63 return c 64 } 65 } 66 } 67 68 // Inject injects an inbound packet. 69 func (e *Endpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) { 70 e.InjectLinkAddr(protocol, "", vv) 71 } 72 73 // InjectLinkAddr injects an inbound packet with a remote link address. 74 func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remote tcpip.LinkAddress, vv buffer.VectorisedView) { 75 e.dispatcher.DeliverNetworkPacket(e, remote, "" /* local */, protocol, vv.Clone(nil)) 76 } 77 78 // Attach saves the stack network-layer dispatcher for use later when packets 79 // are injected. 80 func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { 81 e.dispatcher = dispatcher 82 } 83 84 // IsAttached implements stack.LinkEndpoint.IsAttached. 85 func (e *Endpoint) IsAttached() bool { 86 return e.dispatcher != nil 87 } 88 89 // MTU implements stack.LinkEndpoint.MTU. It returns the value initialized 90 // during construction. 91 func (e *Endpoint) MTU() uint32 { 92 return e.mtu 93 } 94 95 // Capabilities implements stack.LinkEndpoint.Capabilities. 96 func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities { 97 caps := stack.LinkEndpointCapabilities(0) 98 if e.GSO { 99 caps |= stack.CapabilityGSO 100 } 101 return caps 102 } 103 104 // GSOMaxSize returns the maximum GSO packet size. 105 func (*Endpoint) GSOMaxSize() uint32 { 106 return 1 << 15 107 } 108 109 // MaxHeaderLength returns the maximum size of the link layer header. Given it 110 // doesn't have a header, it just returns 0. 111 func (*Endpoint) MaxHeaderLength() uint16 { 112 return 0 113 } 114 115 // LinkAddress returns the link address of this endpoint. 116 func (e *Endpoint) LinkAddress() tcpip.LinkAddress { 117 return e.linkAddr 118 } 119 120 // WritePacket stores outbound packets into the channel. 121 func (e *Endpoint) WritePacket(_ *stack.Route, gso *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { 122 p := PacketInfo{ 123 Header: hdr.View(), 124 Proto: protocol, 125 Payload: payload.ToView(), 126 GSO: gso, 127 } 128 129 select { 130 case e.C <- p: 131 default: 132 } 133 134 return nil 135 } 136 137 // Wait implements stack.LinkEndpoint.Wait. 138 func (*Endpoint) Wait() {}