github.com/FlowerWrong/netstack@v0.0.0-20191009141956-e5848263af28/tcpip/network/ipv6/ipv6.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 ipv6 contains the implementation of the ipv6 network protocol. To use 16 // it in the networking stack, this package must be added to the project, and 17 // activated on the stack by passing ipv6.NewProtocol() as one of the network 18 // protocols when calling stack.New(). Then endpoints can be created by passing 19 // ipv6.ProtocolNumber as the network protocol number when calling 20 // Stack.NewEndpoint(). 21 package ipv6 22 23 import ( 24 "sync/atomic" 25 26 "github.com/FlowerWrong/netstack/tcpip" 27 "github.com/FlowerWrong/netstack/tcpip/buffer" 28 "github.com/FlowerWrong/netstack/tcpip/header" 29 "github.com/FlowerWrong/netstack/tcpip/stack" 30 ) 31 32 const ( 33 // ProtocolNumber is the ipv6 protocol number. 34 ProtocolNumber = header.IPv6ProtocolNumber 35 36 // maxTotalSize is maximum size that can be encoded in the 16-bit 37 // PayloadLength field of the ipv6 header. 38 maxPayloadSize = 0xffff 39 40 // DefaultTTL is the default hop limit for IPv6 Packets egressed by 41 // Netstack. 42 DefaultTTL = 64 43 ) 44 45 type endpoint struct { 46 nicid tcpip.NICID 47 id stack.NetworkEndpointID 48 prefixLen int 49 linkEP stack.LinkEndpoint 50 linkAddrCache stack.LinkAddressCache 51 dispatcher stack.TransportDispatcher 52 protocol *protocol 53 } 54 55 // DefaultTTL is the default hop limit for this endpoint. 56 func (e *endpoint) DefaultTTL() uint8 { 57 return e.protocol.DefaultTTL() 58 } 59 60 // MTU implements stack.NetworkEndpoint.MTU. It returns the link-layer MTU minus 61 // the network layer max header length. 62 func (e *endpoint) MTU() uint32 { 63 return calculateMTU(e.linkEP.MTU()) 64 } 65 66 // NICID returns the ID of the NIC this endpoint belongs to. 67 func (e *endpoint) NICID() tcpip.NICID { 68 return e.nicid 69 } 70 71 // ID returns the ipv6 endpoint ID. 72 func (e *endpoint) ID() *stack.NetworkEndpointID { 73 return &e.id 74 } 75 76 // PrefixLen returns the ipv6 endpoint subnet prefix length in bits. 77 func (e *endpoint) PrefixLen() int { 78 return e.prefixLen 79 } 80 81 // Capabilities implements stack.NetworkEndpoint.Capabilities. 82 func (e *endpoint) Capabilities() stack.LinkEndpointCapabilities { 83 return e.linkEP.Capabilities() 84 } 85 86 // MaxHeaderLength returns the maximum length needed by ipv6 headers (and 87 // underlying protocols). 88 func (e *endpoint) MaxHeaderLength() uint16 { 89 return e.linkEP.MaxHeaderLength() + header.IPv6MinimumSize 90 } 91 92 // GSOMaxSize returns the maximum GSO packet size. 93 func (e *endpoint) GSOMaxSize() uint32 { 94 if gso, ok := e.linkEP.(stack.GSOEndpoint); ok { 95 return gso.GSOMaxSize() 96 } 97 return 0 98 } 99 100 // WritePacket writes a packet to the given destination address and protocol. 101 func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber, ttl uint8, loop stack.PacketLooping) *tcpip.Error { 102 length := uint16(hdr.UsedLength() + payload.Size()) 103 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 104 ip.Encode(&header.IPv6Fields{ 105 PayloadLength: length, 106 NextHeader: uint8(protocol), 107 HopLimit: ttl, 108 SrcAddr: r.LocalAddress, 109 DstAddr: r.RemoteAddress, 110 }) 111 112 if loop&stack.PacketLoop != 0 { 113 views := make([]buffer.View, 1, 1+len(payload.Views())) 114 views[0] = hdr.View() 115 views = append(views, payload.Views()...) 116 vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views) 117 loopedR := r.MakeLoopedRoute() 118 e.HandlePacket(&loopedR, vv) 119 loopedR.Release() 120 } 121 if loop&stack.PacketOut == 0 { 122 return nil 123 } 124 125 r.Stats().IP.PacketsSent.Increment() 126 return e.linkEP.WritePacket(r, gso, hdr, payload, ProtocolNumber) 127 } 128 129 // WriteHeaderIncludedPacker implements stack.NetworkEndpoint. It is not yet 130 // supported by IPv6. 131 func (*endpoint) WriteHeaderIncludedPacket(r *stack.Route, payload buffer.VectorisedView, loop stack.PacketLooping) *tcpip.Error { 132 // TODO(b/119580726): Support IPv6 header-included packets. 133 return tcpip.ErrNotSupported 134 } 135 136 // HandlePacket is called by the link layer when new ipv6 packets arrive for 137 // this endpoint. 138 func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) { 139 headerView := vv.First() 140 h := header.IPv6(headerView) 141 if !h.IsValid(vv.Size()) { 142 return 143 } 144 145 vv.TrimFront(header.IPv6MinimumSize) 146 vv.CapLength(int(h.PayloadLength())) 147 148 p := h.TransportProtocol() 149 if p == header.ICMPv6ProtocolNumber { 150 e.handleICMP(r, headerView, vv) 151 return 152 } 153 154 r.Stats().IP.PacketsDelivered.Increment() 155 e.dispatcher.DeliverTransportPacket(r, p, headerView, vv) 156 } 157 158 // Close cleans up resources associated with the endpoint. 159 func (*endpoint) Close() {} 160 161 type protocol struct { 162 // defaultTTL is the current default TTL for the protocol. Only the 163 // uint8 portion of it is meaningful and it must be accessed 164 // atomically. 165 defaultTTL uint32 166 } 167 168 // Number returns the ipv6 protocol number. 169 func (p *protocol) Number() tcpip.NetworkProtocolNumber { 170 return ProtocolNumber 171 } 172 173 // MinimumPacketSize returns the minimum valid ipv6 packet size. 174 func (p *protocol) MinimumPacketSize() int { 175 return header.IPv6MinimumSize 176 } 177 178 // DefaultPrefixLen returns the IPv6 default prefix length. 179 func (p *protocol) DefaultPrefixLen() int { 180 return header.IPv6AddressSize * 8 181 } 182 183 // ParseAddresses implements NetworkProtocol.ParseAddresses. 184 func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) { 185 h := header.IPv6(v) 186 return h.SourceAddress(), h.DestinationAddress() 187 } 188 189 // NewEndpoint creates a new ipv6 endpoint. 190 func (p *protocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) { 191 return &endpoint{ 192 nicid: nicid, 193 id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address}, 194 prefixLen: addrWithPrefix.PrefixLen, 195 linkEP: linkEP, 196 linkAddrCache: linkAddrCache, 197 dispatcher: dispatcher, 198 protocol: p, 199 }, nil 200 } 201 202 // SetOption implements NetworkProtocol.SetOption. 203 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 204 switch v := option.(type) { 205 case tcpip.DefaultTTLOption: 206 p.SetDefaultTTL(uint8(v)) 207 return nil 208 default: 209 return tcpip.ErrUnknownProtocolOption 210 } 211 } 212 213 // Option implements NetworkProtocol.Option. 214 func (p *protocol) Option(option interface{}) *tcpip.Error { 215 switch v := option.(type) { 216 case *tcpip.DefaultTTLOption: 217 *v = tcpip.DefaultTTLOption(p.DefaultTTL()) 218 return nil 219 default: 220 return tcpip.ErrUnknownProtocolOption 221 } 222 } 223 224 // SetDefaultTTL sets the default TTL for endpoints created with this protocol. 225 func (p *protocol) SetDefaultTTL(ttl uint8) { 226 atomic.StoreUint32(&p.defaultTTL, uint32(ttl)) 227 } 228 229 // DefaultTTL returns the default TTL for endpoints created with this protocol. 230 func (p *protocol) DefaultTTL() uint8 { 231 return uint8(atomic.LoadUint32(&p.defaultTTL)) 232 } 233 234 // calculateMTU calculates the network-layer payload MTU based on the link-layer 235 // payload mtu. 236 func calculateMTU(mtu uint32) uint32 { 237 mtu -= header.IPv6MinimumSize 238 if mtu <= maxPayloadSize { 239 return mtu 240 } 241 return maxPayloadSize 242 } 243 244 // NewProtocol returns an IPv6 network protocol. 245 func NewProtocol() stack.NetworkProtocol { 246 return &protocol{defaultTTL: DefaultTTL} 247 }