github.com/flowerwrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/link/loopback/loopback.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 loopback provides the implemention of loopback data-link layer 16 // endpoints. Such endpoints just turn outbound packets into inbound ones. 17 // 18 // Loopback endpoints can be used in the networking stack by calling New() to 19 // create a new endpoint, and then passing it as an argument to 20 // Stack.CreateNIC(). 21 package loopback 22 23 import ( 24 "github.com/FlowerWrong/netstack/tcpip" 25 "github.com/FlowerWrong/netstack/tcpip/buffer" 26 "github.com/FlowerWrong/netstack/tcpip/stack" 27 ) 28 29 type endpoint struct { 30 dispatcher stack.NetworkDispatcher 31 } 32 33 // New creates a new loopback endpoint. This link-layer endpoint just turns 34 // outbound packets into inbound packets. 35 func New() stack.LinkEndpoint { 36 return &endpoint{} 37 } 38 39 // Attach implements stack.LinkEndpoint.Attach. It just saves the stack network- 40 // layer dispatcher for later use when packets need to be dispatched. 41 func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) { 42 e.dispatcher = dispatcher 43 } 44 45 // IsAttached implements stack.LinkEndpoint.IsAttached. 46 func (e *endpoint) IsAttached() bool { 47 return e.dispatcher != nil 48 } 49 50 // MTU implements stack.LinkEndpoint.MTU. It returns a constant that matches the 51 // linux loopback interface. 52 func (*endpoint) MTU() uint32 { 53 return 65536 54 } 55 56 // Capabilities implements stack.LinkEndpoint.Capabilities. Loopback advertises 57 // itself as supporting checksum offload, but in reality it's just omitted. 58 func (*endpoint) Capabilities() stack.LinkEndpointCapabilities { 59 return stack.CapabilityRXChecksumOffload | stack.CapabilityTXChecksumOffload | stack.CapabilitySaveRestore | stack.CapabilityLoopback 60 } 61 62 // MaxHeaderLength implements stack.LinkEndpoint.MaxHeaderLength. Given that the 63 // loopback interface doesn't have a header, it just returns 0. 64 func (*endpoint) MaxHeaderLength() uint16 { 65 return 0 66 } 67 68 // LinkAddress returns the link address of this endpoint. 69 func (*endpoint) LinkAddress() tcpip.LinkAddress { 70 return "" 71 } 72 73 // WritePacket implements stack.LinkEndpoint.WritePacket. It delivers outbound 74 // packets to the network-layer dispatcher. 75 func (e *endpoint) WritePacket(_ *stack.Route, _ *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { 76 views := make([]buffer.View, 1, 1+len(payload.Views())) 77 views[0] = hdr.View() 78 views = append(views, payload.Views()...) 79 vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views) 80 81 // Because we're immediately turning around and writing the packet back to the 82 // rx path, we intentionally don't preserve the remote and local link 83 // addresses from the stack.Route we're passed. 84 e.dispatcher.DeliverNetworkPacket(e, "" /* remote */, "" /* local */, protocol, vv) 85 86 return nil 87 } 88 89 // Wait implements stack.LinkEndpoint.Wait. 90 func (*endpoint) Wait() {}