github.com/vpnishe/netstack@v1.10.6/tcpip/stack/route.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 stack
    16  
    17  import (
    18  	"github.com/vpnishe/netstack/sleep"
    19  	"github.com/vpnishe/netstack/tcpip"
    20  	"github.com/vpnishe/netstack/tcpip/buffer"
    21  	"github.com/vpnishe/netstack/tcpip/header"
    22  )
    23  
    24  // Route represents a route through the networking stack to a given destination.
    25  type Route struct {
    26  	// RemoteAddress is the final destination of the route.
    27  	RemoteAddress tcpip.Address
    28  
    29  	// RemoteLinkAddress is the link-layer (MAC) address of the
    30  	// final destination of the route.
    31  	RemoteLinkAddress tcpip.LinkAddress
    32  
    33  	// LocalAddress is the local address where the route starts.
    34  	LocalAddress tcpip.Address
    35  
    36  	// LocalLinkAddress is the link-layer (MAC) address of the
    37  	// where the route starts.
    38  	LocalLinkAddress tcpip.LinkAddress
    39  
    40  	// NextHop is the next node in the path to the destination.
    41  	NextHop tcpip.Address
    42  
    43  	// NetProto is the network-layer protocol.
    44  	NetProto tcpip.NetworkProtocolNumber
    45  
    46  	// ref a reference to the network endpoint through which the route
    47  	// starts.
    48  	ref *referencedNetworkEndpoint
    49  
    50  	// Loop controls where WritePacket should send packets.
    51  	Loop PacketLooping
    52  }
    53  
    54  // makeRoute initializes a new route. It takes ownership of the provided
    55  // reference to a network endpoint.
    56  func makeRoute(netProto tcpip.NetworkProtocolNumber, localAddr, remoteAddr tcpip.Address, localLinkAddr tcpip.LinkAddress, ref *referencedNetworkEndpoint, handleLocal, multicastLoop bool) Route {
    57  	loop := PacketOut
    58  	if handleLocal && localAddr != "" && remoteAddr == localAddr {
    59  		loop = PacketLoop
    60  	} else if multicastLoop && (header.IsV4MulticastAddress(remoteAddr) || header.IsV6MulticastAddress(remoteAddr)) {
    61  		loop |= PacketLoop
    62  	} else if remoteAddr == header.IPv4Broadcast {
    63  		loop |= PacketLoop
    64  	}
    65  
    66  	return Route{
    67  		NetProto:         netProto,
    68  		LocalAddress:     localAddr,
    69  		LocalLinkAddress: localLinkAddr,
    70  		RemoteAddress:    remoteAddr,
    71  		ref:              ref,
    72  		Loop:             loop,
    73  	}
    74  }
    75  
    76  // NICID returns the id of the NIC from which this route originates.
    77  func (r *Route) NICID() tcpip.NICID {
    78  	return r.ref.ep.NICID()
    79  }
    80  
    81  // MaxHeaderLength forwards the call to the network endpoint's implementation.
    82  func (r *Route) MaxHeaderLength() uint16 {
    83  	return r.ref.ep.MaxHeaderLength()
    84  }
    85  
    86  // Stats returns a mutable copy of current stats.
    87  func (r *Route) Stats() tcpip.Stats {
    88  	return r.ref.nic.stack.Stats()
    89  }
    90  
    91  // PseudoHeaderChecksum forwards the call to the network endpoint's
    92  // implementation.
    93  func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, totalLen uint16) uint16 {
    94  	return header.PseudoHeaderChecksum(protocol, r.LocalAddress, r.RemoteAddress, totalLen)
    95  }
    96  
    97  // Capabilities returns the link-layer capabilities of the route.
    98  func (r *Route) Capabilities() LinkEndpointCapabilities {
    99  	return r.ref.ep.Capabilities()
   100  }
   101  
   102  // GSOMaxSize returns the maximum GSO packet size.
   103  func (r *Route) GSOMaxSize() uint32 {
   104  	if gso, ok := r.ref.ep.(GSOEndpoint); ok {
   105  		return gso.GSOMaxSize()
   106  	}
   107  	return 0
   108  }
   109  
   110  // Resolve attempts to resolve the link address if necessary. Returns ErrWouldBlock in
   111  // case address resolution requires blocking, e.g. wait for ARP reply. Waker is
   112  // notified when address resolution is complete (success or not).
   113  //
   114  // If address resolution is required, ErrNoLinkAddress and a notification channel is
   115  // returned for the top level caller to block. Channel is closed once address resolution
   116  // is complete (success or not).
   117  func (r *Route) Resolve(waker *sleep.Waker) (<-chan struct{}, *tcpip.Error) {
   118  	if !r.IsResolutionRequired() {
   119  		// Nothing to do if there is no cache (which does the resolution on cache miss) or
   120  		// link address is already known.
   121  		return nil, nil
   122  	}
   123  
   124  	nextAddr := r.NextHop
   125  	if nextAddr == "" {
   126  		// Local link address is already known.
   127  		if r.RemoteAddress == r.LocalAddress {
   128  			r.RemoteLinkAddress = r.LocalLinkAddress
   129  			return nil, nil
   130  		}
   131  		nextAddr = r.RemoteAddress
   132  	}
   133  	linkAddr, ch, err := r.ref.linkCache.GetLinkAddress(r.ref.nic.ID(), nextAddr, r.LocalAddress, r.NetProto, waker)
   134  	if err != nil {
   135  		return ch, err
   136  	}
   137  	r.RemoteLinkAddress = linkAddr
   138  	return nil, nil
   139  }
   140  
   141  // RemoveWaker removes a waker that has been added in Resolve().
   142  func (r *Route) RemoveWaker(waker *sleep.Waker) {
   143  	nextAddr := r.NextHop
   144  	if nextAddr == "" {
   145  		nextAddr = r.RemoteAddress
   146  	}
   147  	r.ref.linkCache.RemoveWaker(r.ref.nic.ID(), nextAddr, waker)
   148  }
   149  
   150  // IsResolutionRequired returns true if Resolve() must be called to resolve
   151  // the link address before the this route can be written to.
   152  func (r *Route) IsResolutionRequired() bool {
   153  	return r.ref.isValidForOutgoing() && r.ref.linkCache != nil && r.RemoteLinkAddress == ""
   154  }
   155  
   156  // WritePacket writes the packet through the given route.
   157  func (r *Route) WritePacket(gso *GSO, params NetworkHeaderParams, pkt tcpip.PacketBuffer) *tcpip.Error {
   158  	if !r.ref.isValidForOutgoing() {
   159  		return tcpip.ErrInvalidEndpointState
   160  	}
   161  
   162  	err := r.ref.ep.WritePacket(r, gso, params, r.Loop, pkt)
   163  	if err != nil {
   164  		r.Stats().IP.OutgoingPacketErrors.Increment()
   165  	} else {
   166  		r.ref.nic.stats.Tx.Packets.Increment()
   167  		r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(pkt.Header.UsedLength() + pkt.Data.Size()))
   168  	}
   169  	return err
   170  }
   171  
   172  // PacketDescriptor is a packet descriptor which contains a packet header and
   173  // offset and size of packet data in a payload view.
   174  type PacketDescriptor struct {
   175  	Hdr  buffer.Prependable
   176  	Off  int
   177  	Size int
   178  }
   179  
   180  // NewPacketDescriptors allocates a set of packet descriptors.
   181  func NewPacketDescriptors(n int, hdrSize int) []PacketDescriptor {
   182  	buf := make([]byte, n*hdrSize)
   183  	hdrs := make([]PacketDescriptor, n)
   184  	for i := range hdrs {
   185  		hdrs[i].Hdr = buffer.NewEmptyPrependableFromView(buf[i*hdrSize:][:hdrSize])
   186  	}
   187  	return hdrs
   188  }
   189  
   190  // WritePackets writes the set of packets through the given route.
   191  func (r *Route) WritePackets(gso *GSO, hdrs []PacketDescriptor, payload buffer.VectorisedView, params NetworkHeaderParams) (int, *tcpip.Error) {
   192  	if !r.ref.isValidForOutgoing() {
   193  		return 0, tcpip.ErrInvalidEndpointState
   194  	}
   195  
   196  	n, err := r.ref.ep.WritePackets(r, gso, hdrs, payload, params, r.Loop)
   197  	if err != nil {
   198  		r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(len(hdrs) - n))
   199  	}
   200  	r.ref.nic.stats.Tx.Packets.IncrementBy(uint64(n))
   201  	payloadSize := 0
   202  	for i := 0; i < n; i++ {
   203  		r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(hdrs[i].Hdr.UsedLength()))
   204  		payloadSize += hdrs[i].Size
   205  	}
   206  	r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(payloadSize))
   207  	return n, err
   208  }
   209  
   210  // WriteHeaderIncludedPacket writes a packet already containing a network
   211  // header through the given route.
   212  func (r *Route) WriteHeaderIncludedPacket(pkt tcpip.PacketBuffer) *tcpip.Error {
   213  	if !r.ref.isValidForOutgoing() {
   214  		return tcpip.ErrInvalidEndpointState
   215  	}
   216  
   217  	if err := r.ref.ep.WriteHeaderIncludedPacket(r, r.Loop, pkt); err != nil {
   218  		r.Stats().IP.OutgoingPacketErrors.Increment()
   219  		return err
   220  	}
   221  	r.ref.nic.stats.Tx.Packets.Increment()
   222  	r.ref.nic.stats.Tx.Bytes.IncrementBy(uint64(pkt.Data.Size()))
   223  	return nil
   224  }
   225  
   226  // DefaultTTL returns the default TTL of the underlying network endpoint.
   227  func (r *Route) DefaultTTL() uint8 {
   228  	return r.ref.ep.DefaultTTL()
   229  }
   230  
   231  // MTU returns the MTU of the underlying network endpoint.
   232  func (r *Route) MTU() uint32 {
   233  	return r.ref.ep.MTU()
   234  }
   235  
   236  // Release frees all resources associated with the route.
   237  func (r *Route) Release() {
   238  	if r.ref != nil {
   239  		r.ref.decRef()
   240  		r.ref = nil
   241  	}
   242  }
   243  
   244  // Clone Clone a route such that the original one can be released and the new
   245  // one will remain valid.
   246  func (r *Route) Clone() Route {
   247  	r.ref.incRef()
   248  	return *r
   249  }
   250  
   251  // MakeLoopedRoute duplicates the given route with special handling for routes
   252  // used for sending multicast or broadcast packets. In those cases the
   253  // multicast/broadcast address is the remote address when sending out, but for
   254  // incoming (looped) packets it becomes the local address. Similarly, the local
   255  // interface address that was the local address going out becomes the remote
   256  // address coming in. This is different to unicast routes where local and
   257  // remote addresses remain the same as they identify location (local vs remote)
   258  // not direction (source vs destination).
   259  func (r *Route) MakeLoopedRoute() Route {
   260  	l := r.Clone()
   261  	if r.RemoteAddress == header.IPv4Broadcast || header.IsV4MulticastAddress(r.RemoteAddress) || header.IsV6MulticastAddress(r.RemoteAddress) {
   262  		l.RemoteAddress, l.LocalAddress = l.LocalAddress, l.RemoteAddress
   263  		l.RemoteLinkAddress = l.LocalLinkAddress
   264  	}
   265  	return l
   266  }
   267  
   268  // Stack returns the instance of the Stack that owns this route.
   269  func (r *Route) Stack() *Stack {
   270  	return r.ref.stack()
   271  }