route.go raw
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 stack
16
17 import (
18 "fmt"
19
20 "gvisor.dev/gvisor/pkg/tcpip"
21 "gvisor.dev/gvisor/pkg/tcpip/header"
22 )
23
24 // Route represents a route through the networking stack to a given destination.
25 //
26 // It is safe to call Route's methods from multiple goroutines.
27 type Route struct {
28 routeInfo routeInfo
29
30 // localAddressNIC is the interface the address is associated with.
31 // TODO(gvisor.dev/issue/4548): Remove this field once we can query the
32 // address's assigned status without the NIC.
33 localAddressNIC *nic
34
35 // mu protects annotated fields below.
36 mu routeRWMutex
37
38 // localAddressEndpoint is the local address this route is associated with.
39 // +checklocks:mu
40 localAddressEndpoint AssignableAddressEndpoint
41
42 // remoteLinkAddress is the link-layer (MAC) address of the next hop.
43 // +checklocks:mu
44 remoteLinkAddress tcpip.LinkAddress
45
46 // outgoingNIC is the interface this route uses to write packets.
47 outgoingNIC *nic
48
49 // linkRes is set if link address resolution is enabled for this protocol on
50 // the route's NIC.
51 linkRes *linkResolver
52
53 // neighborEntry is the cached result of fetching a neighbor entry from the
54 // neighbor cache.
55 // +checklocks:mu
56 neighborEntry *neighborEntry
57
58 // mtu is the maximum transmission unit to use for this route.
59 // If mtu is 0, this field is ignored and the MTU of the outgoing NIC
60 // is used for egress packets.
61 mtu uint32
62 }
63
64 // +stateify savable
65 type routeInfo struct {
66 RemoteAddress tcpip.Address
67
68 LocalAddress tcpip.Address
69
70 LocalLinkAddress tcpip.LinkAddress
71
72 NextHop tcpip.Address
73
74 NetProto tcpip.NetworkProtocolNumber
75
76 Loop PacketLooping
77 }
78
79 // RemoteAddress returns the route's destination.
80 func (r *Route) RemoteAddress() tcpip.Address {
81 return r.routeInfo.RemoteAddress
82 }
83
84 // LocalAddress returns the route's local address.
85 func (r *Route) LocalAddress() tcpip.Address {
86 return r.routeInfo.LocalAddress
87 }
88
89 // LocalLinkAddress returns the route's local link-layer address.
90 func (r *Route) LocalLinkAddress() tcpip.LinkAddress {
91 return r.routeInfo.LocalLinkAddress
92 }
93
94 // NextHop returns the next node in the route's path to the destination.
95 func (r *Route) NextHop() tcpip.Address {
96 return r.routeInfo.NextHop
97 }
98
99 // NetProto returns the route's network-layer protocol number.
100 func (r *Route) NetProto() tcpip.NetworkProtocolNumber {
101 return r.routeInfo.NetProto
102 }
103
104 // Loop returns the route's required packet looping.
105 func (r *Route) Loop() PacketLooping {
106 return r.routeInfo.Loop
107 }
108
109 // OutgoingNIC returns the route's outgoing NIC.
110 func (r *Route) OutgoingNIC() tcpip.NICID {
111 return r.outgoingNIC.id
112 }
113
114 // RouteInfo contains all of Route's exported fields.
115 //
116 // +stateify savable
117 type RouteInfo struct {
118 routeInfo
119
120 // RemoteLinkAddress is the link-layer (MAC) address of the next hop in the
121 // route.
122 RemoteLinkAddress tcpip.LinkAddress
123 }
124
125 // Fields returns a RouteInfo with all of the known values for the route's
126 // fields.
127 //
128 // If any fields are unknown (e.g. remote link address when it is waiting for
129 // link address resolution), they will be unset.
130 func (r *Route) Fields() RouteInfo {
131 r.mu.RLock()
132 defer r.mu.RUnlock()
133 return r.fieldsLocked()
134 }
135
136 // +checklocksread:r.mu
137 func (r *Route) fieldsLocked() RouteInfo {
138 return RouteInfo{
139 routeInfo: r.routeInfo,
140 RemoteLinkAddress: r.remoteLinkAddress,
141 }
142 }
143
144 // constructAndValidateRoute validates and initializes a route. It takes
145 // ownership of the provided local address.
146 //
147 // Returns an empty route if validation fails.
148 func constructAndValidateRoute(netProto tcpip.NetworkProtocolNumber, addressEndpoint AssignableAddressEndpoint, localAddressNIC, outgoingNIC *nic, gateway, localAddr, remoteAddr tcpip.Address, handleLocal, multicastLoop bool, mtu uint32) *Route {
149 if localAddr.BitLen() == 0 {
150 localAddr = addressEndpoint.AddressWithPrefix().Address
151 }
152
153 if localAddressNIC != outgoingNIC && header.IsV6LinkLocalUnicastAddress(localAddr) {
154 addressEndpoint.DecRef()
155 return nil
156 }
157
158 // If no remote address is provided, use the local address.
159 if remoteAddr.BitLen() == 0 {
160 remoteAddr = localAddr
161 }
162
163 r := makeRoute(
164 netProto,
165 gateway,
166 localAddr,
167 remoteAddr,
168 outgoingNIC,
169 localAddressNIC,
170 addressEndpoint,
171 handleLocal,
172 multicastLoop,
173 mtu,
174 )
175
176 return r
177 }
178
179 // makeRoute initializes a new route. It takes ownership of the provided
180 // AssignableAddressEndpoint.
181 func makeRoute(netProto tcpip.NetworkProtocolNumber, gateway, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, handleLocal, multicastLoop bool, mtu uint32) *Route {
182 if localAddressNIC.stack != outgoingNIC.stack {
183 panic(fmt.Sprintf("cannot create a route with NICs from different stacks"))
184 }
185
186 if localAddr.BitLen() == 0 {
187 localAddr = localAddressEndpoint.AddressWithPrefix().Address
188 }
189
190 loop := PacketOut
191
192 // Loopback interface loops back packets at the link endpoint level. We
193 // could remove this check if loopback interfaces looped back packets
194 // at the network layer.
195 if !outgoingNIC.IsLoopback() {
196 if handleLocal && localAddr != (tcpip.Address{}) && remoteAddr == localAddr {
197 loop = PacketLoop
198 } else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) {
199 loop |= PacketLoop
200 } else if remoteAddr == header.IPv4Broadcast {
201 loop |= PacketLoop
202 } else if subnet := localAddressEndpoint.AddressWithPrefix().Subnet(); subnet.IsBroadcast(remoteAddr) {
203 loop |= PacketLoop
204 }
205 }
206
207 r := makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop, mtu)
208 if r.Loop()&PacketOut == 0 {
209 // Packet will not leave the stack, no need for a gateway or a remote link
210 // address.
211 return r
212 }
213
214 if r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityResolutionRequired != 0 {
215 if linkRes, ok := r.outgoingNIC.linkAddrResolvers[r.NetProto()]; ok {
216 r.linkRes = linkRes
217 }
218 }
219
220 if gateway.BitLen() > 0 {
221 r.routeInfo.NextHop = gateway
222 return r
223 }
224
225 if r.linkRes == nil {
226 return r
227 }
228
229 if linkAddr, ok := r.linkRes.resolver.ResolveStaticAddress(r.RemoteAddress()); ok {
230 r.ResolveWith(linkAddr)
231 return r
232 }
233
234 if subnet := localAddressEndpoint.Subnet(); subnet.IsBroadcast(remoteAddr) {
235 r.ResolveWith(header.EthernetBroadcastAddress)
236 return r
237 }
238
239 if r.RemoteAddress() == r.LocalAddress() {
240 // Local link address is already known.
241 r.ResolveWith(r.LocalLinkAddress())
242 }
243
244 return r
245 }
246
247 func makeRouteInner(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint, loop PacketLooping, mtu uint32) *Route {
248 r := &Route{
249 routeInfo: routeInfo{
250 NetProto: netProto,
251 LocalAddress: localAddr,
252 LocalLinkAddress: outgoingNIC.NetworkLinkEndpoint.LinkAddress(),
253 RemoteAddress: remoteAddr,
254 Loop: loop,
255 },
256 localAddressNIC: localAddressNIC,
257 outgoingNIC: outgoingNIC,
258 mtu: mtu,
259 }
260
261 r.mu.Lock()
262 r.localAddressEndpoint = localAddressEndpoint
263 r.mu.Unlock()
264
265 return r
266 }
267
268 // makeLocalRoute initializes a new local route. It takes ownership of the
269 // provided AssignableAddressEndpoint.
270 //
271 // A local route is a route to a destination that is local to the stack.
272 func makeLocalRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, outgoingNIC, localAddressNIC *nic, localAddressEndpoint AssignableAddressEndpoint) *Route {
273 loop := PacketLoop
274 // Loopback interface loops back packets at the link endpoint level. We
275 // could remove this check if loopback interfaces looped back packets
276 // at the network layer.
277 if outgoingNIC.IsLoopback() {
278 loop = PacketOut
279 }
280 return makeRouteInner(netProto, localAddr, remoteAddr, outgoingNIC, localAddressNIC, localAddressEndpoint, loop, 0 /* mtu */)
281 }
282
283 // RemoteLinkAddress returns the link-layer (MAC) address of the next hop in
284 // the route.
285 func (r *Route) RemoteLinkAddress() tcpip.LinkAddress {
286 r.mu.RLock()
287 defer r.mu.RUnlock()
288 return r.remoteLinkAddress
289 }
290
291 // NICID returns the id of the NIC from which this route originates.
292 func (r *Route) NICID() tcpip.NICID {
293 return r.outgoingNIC.ID()
294 }
295
296 // MaxHeaderLength forwards the call to the network endpoint's implementation.
297 func (r *Route) MaxHeaderLength() uint16 {
298 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MaxHeaderLength()
299 }
300
301 // Stats returns a mutable copy of current stats.
302 func (r *Route) Stats() tcpip.Stats {
303 return r.outgoingNIC.stack.Stats()
304 }
305
306 // PseudoHeaderChecksum forwards the call to the network endpoint's
307 // implementation.
308 func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, totalLen uint16) uint16 {
309 return header.PseudoHeaderChecksum(protocol, r.LocalAddress(), r.RemoteAddress(), totalLen)
310 }
311
312 // RequiresTXTransportChecksum returns false if the route does not require
313 // transport checksums to be populated.
314 func (r *Route) RequiresTXTransportChecksum() bool {
315 if r.local() {
316 return false
317 }
318 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityTXChecksumOffload == 0
319 }
320
321 // HasGVisorGSOCapability returns true if the route supports gVisor GSO.
322 func (r *Route) HasGVisorGSOCapability() bool {
323 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
324 return gso.SupportedGSO() == GVisorGSOSupported
325 }
326 return false
327 }
328
329 // HasHostGSOCapability returns true if the route supports host GSO.
330 func (r *Route) HasHostGSOCapability() bool {
331 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
332 return gso.SupportedGSO() == HostGSOSupported
333 }
334 return false
335 }
336
337 // HasSaveRestoreCapability returns true if the route supports save/restore.
338 func (r *Route) HasSaveRestoreCapability() bool {
339 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilitySaveRestore != 0
340 }
341
342 // HasDisconnectOkCapability returns true if the route supports disconnecting.
343 func (r *Route) HasDisconnectOkCapability() bool {
344 return r.outgoingNIC.NetworkLinkEndpoint.Capabilities()&CapabilityDisconnectOk != 0
345 }
346
347 // GSOMaxSize returns the maximum GSO packet size.
348 func (r *Route) GSOMaxSize() uint32 {
349 if gso, ok := r.outgoingNIC.NetworkLinkEndpoint.(GSOEndpoint); ok {
350 return gso.GSOMaxSize()
351 }
352 return 0
353 }
354
355 // ResolveWith immediately resolves a route with the specified remote link
356 // address.
357 func (r *Route) ResolveWith(addr tcpip.LinkAddress) {
358 r.mu.Lock()
359 defer r.mu.Unlock()
360 r.remoteLinkAddress = addr
361 }
362
363 // ResolvedFieldsResult is the result of a route resolution attempt.
364 type ResolvedFieldsResult struct {
365 RouteInfo RouteInfo
366 Err tcpip.Error
367 }
368
369 // ResolvedFields attempts to resolve the remote link address if it is not
370 // known.
371 //
372 // If a callback is provided, it will be called before ResolvedFields returns
373 // when address resolution is not required. If address resolution is required,
374 // the callback will be called once address resolution is complete, regardless
375 // of success or failure.
376 //
377 // Note, the route will not cache the remote link address when address
378 // resolution completes.
379 func (r *Route) ResolvedFields(afterResolve func(ResolvedFieldsResult)) tcpip.Error {
380 _, _, err := r.resolvedFields(afterResolve)
381 return err
382 }
383
384 // resolvedFields is like ResolvedFields but also returns a notification channel
385 // when address resolution is required. This channel will become readable once
386 // address resolution is complete.
387 //
388 // The route's fields will also be returned, regardless of whether address
389 // resolution is required or not.
390 func (r *Route) resolvedFields(afterResolve func(ResolvedFieldsResult)) (RouteInfo, <-chan struct{}, tcpip.Error) {
391 r.mu.RLock()
392 fields := r.fieldsLocked()
393 resolutionRequired := r.isResolutionRequiredRLocked()
394 r.mu.RUnlock()
395 if !resolutionRequired {
396 if afterResolve != nil {
397 afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil})
398 }
399 return fields, nil, nil
400 }
401
402 // If specified, the local address used for link address resolution must be an
403 // address on the outgoing interface.
404 var linkAddressResolutionRequestLocalAddr tcpip.Address
405 if r.localAddressNIC == r.outgoingNIC {
406 linkAddressResolutionRequestLocalAddr = r.LocalAddress()
407 }
408
409 nEntry := r.getCachedNeighborEntry()
410 if nEntry != nil {
411 if addr, ok := nEntry.getRemoteLinkAddress(); ok {
412 fields.RemoteLinkAddress = addr
413 if afterResolve != nil {
414 afterResolve(ResolvedFieldsResult{RouteInfo: fields, Err: nil})
415 }
416 return fields, nil, nil
417 }
418 }
419 afterResolveFields := fields
420 entry, ch, err := r.linkRes.neigh.entry(r.nextHop(), linkAddressResolutionRequestLocalAddr, func(lrr LinkResolutionResult) {
421 if afterResolve != nil {
422 if lrr.Err == nil {
423 afterResolveFields.RemoteLinkAddress = lrr.LinkAddress
424 }
425
426 afterResolve(ResolvedFieldsResult{RouteInfo: afterResolveFields, Err: lrr.Err})
427 }
428 })
429 if err == nil {
430 fields.RemoteLinkAddress, _ = entry.getRemoteLinkAddress()
431 }
432 r.setCachedNeighborEntry(entry)
433 return fields, ch, err
434 }
435
436 func (r *Route) getCachedNeighborEntry() *neighborEntry {
437 r.mu.RLock()
438 defer r.mu.RUnlock()
439 return r.neighborEntry
440 }
441
442 func (r *Route) setCachedNeighborEntry(entry *neighborEntry) {
443 r.mu.Lock()
444 defer r.mu.Unlock()
445 r.neighborEntry = entry
446 }
447
448 func (r *Route) nextHop() tcpip.Address {
449 if r.NextHop().BitLen() == 0 {
450 return r.RemoteAddress()
451 }
452 return r.NextHop()
453 }
454
455 // local returns true if the route is a local route.
456 func (r *Route) local() bool {
457 return r.Loop() == PacketLoop || r.outgoingNIC.IsLoopback()
458 }
459
460 // IsResolutionRequired returns true if Resolve() must be called to resolve
461 // the link address before the route can be written to.
462 //
463 // The NICs the route is associated with must not be locked.
464 func (r *Route) IsResolutionRequired() bool {
465 r.mu.RLock()
466 defer r.mu.RUnlock()
467 return r.isResolutionRequiredRLocked()
468 }
469
470 // +checklocksread:r.mu
471 func (r *Route) isResolutionRequiredRLocked() bool {
472 return len(r.remoteLinkAddress) == 0 && r.linkRes != nil && r.isValidForOutgoingRLocked() && !r.local()
473 }
474
475 func (r *Route) isValidForOutgoing() bool {
476 r.mu.RLock()
477 defer r.mu.RUnlock()
478 return r.isValidForOutgoingRLocked()
479 }
480
481 // +checklocksread:r.mu
482 func (r *Route) isValidForOutgoingRLocked() bool {
483 if !r.outgoingNIC.Enabled() {
484 return false
485 }
486
487 localAddressEndpoint := r.localAddressEndpoint
488 if localAddressEndpoint == nil || !r.localAddressNIC.isValidForOutgoing(localAddressEndpoint) {
489 return false
490 }
491
492 // If the source NIC and outgoing NIC are different, make sure the stack has
493 // forwarding enabled, or the packet will be handled locally.
494 if r.outgoingNIC != r.localAddressNIC && !isNICForwarding(r.localAddressNIC, r.NetProto()) && (!r.outgoingNIC.stack.handleLocal || !r.outgoingNIC.hasAddress(r.NetProto(), r.RemoteAddress())) {
495 return false
496 }
497
498 return true
499 }
500
501 // WritePacket writes the packet through the given route.
502 func (r *Route) WritePacket(params NetworkHeaderParams, pkt *PacketBuffer) tcpip.Error {
503 if !r.isValidForOutgoing() {
504 return &tcpip.ErrInvalidEndpointState{}
505 }
506
507 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WritePacket(r, params, pkt)
508 }
509
510 // WriteHeaderIncludedPacket writes a packet already containing a network
511 // header through the given route.
512 func (r *Route) WriteHeaderIncludedPacket(pkt *PacketBuffer) tcpip.Error {
513 if !r.isValidForOutgoing() {
514 return &tcpip.ErrInvalidEndpointState{}
515 }
516
517 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).WriteHeaderIncludedPacket(r, pkt)
518 }
519
520 // DefaultTTL returns the default TTL of the underlying network endpoint.
521 func (r *Route) DefaultTTL() uint8 {
522 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).DefaultTTL()
523 }
524
525 // MTU returns the MTU of the route if present, otherwise the MTU of the underlying network endpoint.
526 func (r *Route) MTU() uint32 {
527 if r.mtu > 0 {
528 return r.mtu
529 }
530 return r.outgoingNIC.getNetworkEndpoint(r.NetProto()).MTU()
531 }
532
533 // Release decrements the reference counter of the resources associated with the
534 // route.
535 func (r *Route) Release() {
536 r.mu.Lock()
537 defer r.mu.Unlock()
538
539 if ep := r.localAddressEndpoint; ep != nil {
540 ep.DecRef()
541 }
542 }
543
544 // Acquire increments the reference counter of the resources associated with the
545 // route.
546 func (r *Route) Acquire() {
547 r.mu.RLock()
548 defer r.mu.RUnlock()
549 r.acquireLocked()
550 }
551
552 // +checklocksread:r.mu
553 func (r *Route) acquireLocked() {
554 if ep := r.localAddressEndpoint; ep != nil {
555 if !ep.TryIncRef() {
556 panic(fmt.Sprintf("failed to increment reference count for local address endpoint = %s", r.LocalAddress()))
557 }
558 }
559 }
560
561 // Stack returns the instance of the Stack that owns this route.
562 func (r *Route) Stack() *Stack {
563 return r.outgoingNIC.stack
564 }
565
566 func (r *Route) isV4Broadcast(addr tcpip.Address) bool {
567 if addr == header.IPv4Broadcast {
568 return true
569 }
570
571 r.mu.RLock()
572 localAddressEndpoint := r.localAddressEndpoint
573 r.mu.RUnlock()
574 if localAddressEndpoint == nil {
575 return false
576 }
577
578 subnet := localAddressEndpoint.Subnet()
579 return subnet.IsBroadcast(addr)
580 }
581
582 // IsOutboundBroadcast returns true if the route is for an outbound broadcast
583 // packet.
584 func (r *Route) IsOutboundBroadcast() bool {
585 // Only IPv4 has a notion of broadcast.
586 return r.isV4Broadcast(r.RemoteAddress())
587 }
588
589 // ConfirmReachable informs the network/link layer that the neighbour used for
590 // the route is reachable.
591 //
592 // "Reachable" is defined as having full-duplex communication between the
593 // local and remote ends of the route.
594 func (r *Route) ConfirmReachable() {
595 if entry := r.getCachedNeighborEntry(); entry != nil {
596 entry.handleUpperLevelConfirmation()
597 }
598 }
599