inet.af/netstack@v0.0.0-20220214151720-7585b01ddccf/tcpip/link/loopback/loopback.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 loopback provides the implemention of loopback data-link layer
    16  // endpoints. Such endpoints just turn outbound packets into inbound ones.
    17  //
    18  // Loopback endpoints can be used in the networking stack by calling New() to
    19  // create a new endpoint, and then passing it as an argument to
    20  // Stack.CreateNIC().
    21  package loopback
    22  
    23  import (
    24  	"inet.af/netstack/tcpip"
    25  	"inet.af/netstack/tcpip/buffer"
    26  	"inet.af/netstack/tcpip/header"
    27  	"inet.af/netstack/tcpip/stack"
    28  )
    29  
    30  type endpoint struct {
    31  	dispatcher stack.NetworkDispatcher
    32  }
    33  
    34  // New creates a new loopback endpoint. This link-layer endpoint just turns
    35  // outbound packets into inbound packets.
    36  func New() stack.LinkEndpoint {
    37  	return &endpoint{}
    38  }
    39  
    40  // Attach implements stack.LinkEndpoint.Attach. It just saves the stack network-
    41  // layer dispatcher for later use when packets need to be dispatched.
    42  func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
    43  	e.dispatcher = dispatcher
    44  }
    45  
    46  // IsAttached implements stack.LinkEndpoint.IsAttached.
    47  func (e *endpoint) IsAttached() bool {
    48  	return e.dispatcher != nil
    49  }
    50  
    51  // MTU implements stack.LinkEndpoint.MTU. It returns a constant that matches the
    52  // linux loopback interface.
    53  func (*endpoint) MTU() uint32 {
    54  	return 65536
    55  }
    56  
    57  // Capabilities implements stack.LinkEndpoint.Capabilities. Loopback advertises
    58  // itself as supporting checksum offload, but in reality it's just omitted.
    59  func (*endpoint) Capabilities() stack.LinkEndpointCapabilities {
    60  	return stack.CapabilityRXChecksumOffload | stack.CapabilityTXChecksumOffload | stack.CapabilitySaveRestore | stack.CapabilityLoopback
    61  }
    62  
    63  // MaxHeaderLength implements stack.LinkEndpoint.MaxHeaderLength. Given that the
    64  // loopback interface doesn't have a header, it just returns 0.
    65  func (*endpoint) MaxHeaderLength() uint16 {
    66  	return 0
    67  }
    68  
    69  // LinkAddress returns the link address of this endpoint.
    70  func (*endpoint) LinkAddress() tcpip.LinkAddress {
    71  	return ""
    72  }
    73  
    74  // Wait implements stack.LinkEndpoint.Wait.
    75  func (*endpoint) Wait() {}
    76  
    77  // WritePacket implements stack.LinkEndpoint.WritePacket. It delivers outbound
    78  // packets to the network-layer dispatcher.
    79  func (e *endpoint) WritePacket(_ stack.RouteInfo, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
    80  	return e.WriteRawPacket(pkt)
    81  }
    82  
    83  // WritePackets implements stack.LinkEndpoint.WritePackets.
    84  func (e *endpoint) WritePackets(stack.RouteInfo, stack.PacketBufferList, tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
    85  	panic("not implemented")
    86  }
    87  
    88  // ARPHardwareType implements stack.LinkEndpoint.ARPHardwareType.
    89  func (*endpoint) ARPHardwareType() header.ARPHardwareType {
    90  	return header.ARPHardwareLoopback
    91  }
    92  
    93  func (e *endpoint) AddHeader(local, remote tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
    94  }
    95  
    96  // WriteRawPacket implements stack.LinkEndpoint.
    97  func (e *endpoint) WriteRawPacket(pkt *stack.PacketBuffer) tcpip.Error {
    98  	// Construct data as the unparsed portion for the loopback packet.
    99  	data := buffer.NewVectorisedView(pkt.Size(), pkt.Views())
   100  
   101  	// Because we're immediately turning around and writing the packet back
   102  	// to the rx path, we intentionally don't preserve the remote and local
   103  	// link addresses from the stack.Route we're passed.
   104  	newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
   105  		Data: data,
   106  	})
   107  	defer newPkt.DecRef()
   108  	e.dispatcher.DeliverNetworkPacket("" /* remote */, "" /* local */, pkt.NetworkProtocolNumber, newPkt)
   109  
   110  	return nil
   111  }