github.com/noisysockets/netstack@v0.6.0/pkg/tcpip/link/pipe/pipe.go (about) 1 // Copyright 2020 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 pipe provides the implementation of pipe-like data-link layer 16 // endpoints. Such endpoints allow packets to be sent between two interfaces. 17 package pipe 18 19 import ( 20 "sync" 21 22 "github.com/noisysockets/netstack/pkg/tcpip" 23 "github.com/noisysockets/netstack/pkg/tcpip/header" 24 "github.com/noisysockets/netstack/pkg/tcpip/stack" 25 ) 26 27 var _ stack.LinkEndpoint = (*Endpoint)(nil) 28 29 // New returns both ends of a new pipe. 30 func New(linkAddr1, linkAddr2 tcpip.LinkAddress, mtu uint32) (*Endpoint, *Endpoint) { 31 ep1 := &Endpoint{ 32 linkAddr: linkAddr1, 33 mtu: mtu, 34 } 35 ep2 := &Endpoint{ 36 linkAddr: linkAddr2, 37 mtu: mtu, 38 } 39 ep1.linked = ep2 40 ep2.linked = ep1 41 return ep1, ep2 42 } 43 44 // Endpoint is one end of a pipe. 45 type Endpoint struct { 46 linked *Endpoint 47 linkAddr tcpip.LinkAddress 48 mtu uint32 49 50 mu sync.RWMutex 51 // +checklocks:mu 52 dispatcher stack.NetworkDispatcher 53 } 54 55 func (e *Endpoint) deliverPackets(pkts stack.PacketBufferList) { 56 if !e.linked.IsAttached() { 57 return 58 } 59 60 for _, pkt := range pkts.AsSlice() { 61 // Create a fresh packet with pkt's payload but without struct fields 62 // or headers set so the next link protocol can properly set the link 63 // header. 64 newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ 65 Payload: pkt.ToBuffer(), 66 }) 67 e.linked.mu.RLock() 68 d := e.linked.dispatcher 69 e.linked.mu.RUnlock() 70 d.DeliverNetworkPacket(pkt.NetworkProtocolNumber, newPkt) 71 newPkt.DecRef() 72 } 73 } 74 75 // WritePackets implements stack.LinkEndpoint. 76 func (e *Endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) { 77 n := pkts.Len() 78 e.deliverPackets(pkts) 79 return n, nil 80 } 81 82 // Attach implements stack.LinkEndpoint. 83 func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { 84 e.mu.Lock() 85 defer e.mu.Unlock() 86 e.dispatcher = dispatcher 87 } 88 89 // IsAttached implements stack.LinkEndpoint. 90 func (e *Endpoint) IsAttached() bool { 91 e.mu.RLock() 92 defer e.mu.RUnlock() 93 return e.dispatcher != nil 94 } 95 96 // Wait implements stack.LinkEndpoint. 97 func (*Endpoint) Wait() {} 98 99 // MTU implements stack.LinkEndpoint. 100 func (e *Endpoint) MTU() uint32 { 101 return e.mtu 102 } 103 104 // Capabilities implements stack.LinkEndpoint. 105 func (*Endpoint) Capabilities() stack.LinkEndpointCapabilities { 106 return 0 107 } 108 109 // MaxHeaderLength implements stack.LinkEndpoint. 110 func (*Endpoint) MaxHeaderLength() uint16 { 111 return 0 112 } 113 114 // LinkAddress implements stack.LinkEndpoint. 115 func (e *Endpoint) LinkAddress() tcpip.LinkAddress { 116 return e.linkAddr 117 } 118 119 // ARPHardwareType implements stack.LinkEndpoint. 120 func (*Endpoint) ARPHardwareType() header.ARPHardwareType { 121 return header.ARPHardwareNone 122 } 123 124 // AddHeader implements stack.LinkEndpoint. 125 func (*Endpoint) AddHeader(*stack.PacketBuffer) {} 126 127 // ParseHeader implements stack.LinkEndpoint. 128 func (*Endpoint) ParseHeader(*stack.PacketBuffer) bool { return true }