github.com/lightlus/netstack@v1.2.0/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/lightlus/netstack/tcpip" 27 "github.com/lightlus/netstack/tcpip/buffer" 28 "github.com/lightlus/netstack/tcpip/header" 29 "github.com/lightlus/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 func (e *endpoint) addIPHeader(r *stack.Route, hdr *buffer.Prependable, payloadSize int, params stack.NetworkHeaderParams) header.IPv6 { 101 length := uint16(hdr.UsedLength() + payloadSize) 102 ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize)) 103 ip.Encode(&header.IPv6Fields{ 104 PayloadLength: length, 105 NextHeader: uint8(params.Protocol), 106 HopLimit: params.TTL, 107 TrafficClass: params.TOS, 108 SrcAddr: r.LocalAddress, 109 DstAddr: r.RemoteAddress, 110 }) 111 return ip 112 } 113 114 // WritePacket writes a packet to the given destination address and protocol. 115 func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, params stack.NetworkHeaderParams, loop stack.PacketLooping, pkt tcpip.PacketBuffer) *tcpip.Error { 116 ip := e.addIPHeader(r, &pkt.Header, pkt.Data.Size(), params) 117 118 if loop&stack.PacketLoop != 0 { 119 views := make([]buffer.View, 1, 1+len(pkt.Data.Views())) 120 views[0] = pkt.Header.View() 121 views = append(views, pkt.Data.Views()...) 122 loopedR := r.MakeLoopedRoute() 123 124 e.HandlePacket(&loopedR, tcpip.PacketBuffer{ 125 Data: buffer.NewVectorisedView(len(views[0])+pkt.Data.Size(), views), 126 NetworkHeader: buffer.View(ip), 127 }) 128 129 loopedR.Release() 130 } 131 if loop&stack.PacketOut == 0 { 132 return nil 133 } 134 135 r.Stats().IP.PacketsSent.Increment() 136 return e.linkEP.WritePacket(r, gso, ProtocolNumber, pkt) 137 } 138 139 // WritePackets implements stack.LinkEndpoint.WritePackets. 140 func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, hdrs []stack.PacketDescriptor, payload buffer.VectorisedView, params stack.NetworkHeaderParams, loop stack.PacketLooping) (int, *tcpip.Error) { 141 if loop&stack.PacketLoop != 0 { 142 panic("not implemented") 143 } 144 if loop&stack.PacketOut == 0 { 145 return len(hdrs), nil 146 } 147 148 for i := range hdrs { 149 hdr := &hdrs[i].Hdr 150 size := hdrs[i].Size 151 e.addIPHeader(r, hdr, size, params) 152 } 153 154 n, err := e.linkEP.WritePackets(r, gso, hdrs, payload, ProtocolNumber) 155 r.Stats().IP.PacketsSent.IncrementBy(uint64(n)) 156 return n, err 157 } 158 159 // WriteHeaderIncludedPacker implements stack.NetworkEndpoint. It is not yet 160 // supported by IPv6. 161 func (*endpoint) WriteHeaderIncludedPacket(r *stack.Route, loop stack.PacketLooping, pkt tcpip.PacketBuffer) *tcpip.Error { 162 // TODO(b/119580726): Support IPv6 header-included packets. 163 return tcpip.ErrNotSupported 164 } 165 166 // HandlePacket is called by the link layer when new ipv6 packets arrive for 167 // this endpoint. 168 func (e *endpoint) HandlePacket(r *stack.Route, pkt tcpip.PacketBuffer) { 169 headerView := pkt.Data.First() 170 h := header.IPv6(headerView) 171 if !h.IsValid(pkt.Data.Size()) { 172 return 173 } 174 175 pkt.NetworkHeader = headerView[:header.IPv6MinimumSize] 176 pkt.Data.TrimFront(header.IPv6MinimumSize) 177 pkt.Data.CapLength(int(h.PayloadLength())) 178 179 p := h.TransportProtocol() 180 if p == header.ICMPv6ProtocolNumber { 181 e.handleICMP(r, headerView, pkt) 182 return 183 } 184 185 r.Stats().IP.PacketsDelivered.Increment() 186 e.dispatcher.DeliverTransportPacket(r, p, pkt) 187 } 188 189 // Close cleans up resources associated with the endpoint. 190 func (*endpoint) Close() {} 191 192 type protocol struct { 193 // defaultTTL is the current default TTL for the protocol. Only the 194 // uint8 portion of it is meaningful and it must be accessed 195 // atomically. 196 defaultTTL uint32 197 } 198 199 // Number returns the ipv6 protocol number. 200 func (p *protocol) Number() tcpip.NetworkProtocolNumber { 201 return ProtocolNumber 202 } 203 204 // MinimumPacketSize returns the minimum valid ipv6 packet size. 205 func (p *protocol) MinimumPacketSize() int { 206 return header.IPv6MinimumSize 207 } 208 209 // DefaultPrefixLen returns the IPv6 default prefix length. 210 func (p *protocol) DefaultPrefixLen() int { 211 return header.IPv6AddressSize * 8 212 } 213 214 // ParseAddresses implements NetworkProtocol.ParseAddresses. 215 func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) { 216 h := header.IPv6(v) 217 return h.SourceAddress(), h.DestinationAddress() 218 } 219 220 // NewEndpoint creates a new ipv6 endpoint. 221 func (p *protocol) NewEndpoint(nicID tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) { 222 return &endpoint{ 223 nicID: nicID, 224 id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address}, 225 prefixLen: addrWithPrefix.PrefixLen, 226 linkEP: linkEP, 227 linkAddrCache: linkAddrCache, 228 dispatcher: dispatcher, 229 protocol: p, 230 }, nil 231 } 232 233 // SetOption implements NetworkProtocol.SetOption. 234 func (p *protocol) SetOption(option interface{}) *tcpip.Error { 235 switch v := option.(type) { 236 case tcpip.DefaultTTLOption: 237 p.SetDefaultTTL(uint8(v)) 238 return nil 239 default: 240 return tcpip.ErrUnknownProtocolOption 241 } 242 } 243 244 // Option implements NetworkProtocol.Option. 245 func (p *protocol) Option(option interface{}) *tcpip.Error { 246 switch v := option.(type) { 247 case *tcpip.DefaultTTLOption: 248 *v = tcpip.DefaultTTLOption(p.DefaultTTL()) 249 return nil 250 default: 251 return tcpip.ErrUnknownProtocolOption 252 } 253 } 254 255 // SetDefaultTTL sets the default TTL for endpoints created with this protocol. 256 func (p *protocol) SetDefaultTTL(ttl uint8) { 257 atomic.StoreUint32(&p.defaultTTL, uint32(ttl)) 258 } 259 260 // DefaultTTL returns the default TTL for endpoints created with this protocol. 261 func (p *protocol) DefaultTTL() uint8 { 262 return uint8(atomic.LoadUint32(&p.defaultTTL)) 263 } 264 265 // calculateMTU calculates the network-layer payload MTU based on the link-layer 266 // payload mtu. 267 func calculateMTU(mtu uint32) uint32 { 268 mtu -= header.IPv6MinimumSize 269 if mtu <= maxPayloadSize { 270 return mtu 271 } 272 return maxPayloadSize 273 } 274 275 // NewProtocol returns an IPv6 network protocol. 276 func NewProtocol() stack.NetworkProtocol { 277 return &protocol{defaultTTL: DefaultTTL} 278 }