github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/tcpip/link/ethernet/ethernet.go (about)

     1  // Copyright 2020 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 ethernet provides an implementation of an ethernet link endpoint that
    16  // wraps an inner link endpoint.
    17  package ethernet
    18  
    19  import (
    20  	"github.com/SagerNet/gvisor/pkg/tcpip"
    21  	"github.com/SagerNet/gvisor/pkg/tcpip/header"
    22  	"github.com/SagerNet/gvisor/pkg/tcpip/link/nested"
    23  	"github.com/SagerNet/gvisor/pkg/tcpip/stack"
    24  )
    25  
    26  var _ stack.NetworkDispatcher = (*Endpoint)(nil)
    27  var _ stack.LinkEndpoint = (*Endpoint)(nil)
    28  
    29  // New returns an ethernet link endpoint that wraps an inner link endpoint.
    30  func New(ep stack.LinkEndpoint) *Endpoint {
    31  	var e Endpoint
    32  	e.Endpoint.Init(ep, &e)
    33  	return &e
    34  }
    35  
    36  // Endpoint is an ethernet endpoint.
    37  //
    38  // It adds an ethernet header to packets before sending them out through its
    39  // inner link endpoint and consumes an ethernet header before sending the
    40  // packet to the stack.
    41  type Endpoint struct {
    42  	nested.Endpoint
    43  }
    44  
    45  // DeliverNetworkPacket implements stack.NetworkDispatcher.
    46  func (e *Endpoint) DeliverNetworkPacket(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
    47  	hdr, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
    48  	if !ok {
    49  		return
    50  	}
    51  
    52  	// Note, there is no need to check the destination link address here since
    53  	// the ethernet hardware filters frames based on their destination addresses.
    54  	eth := header.Ethernet(hdr)
    55  	e.Endpoint.DeliverNetworkPacket(eth.SourceAddress() /* remote */, eth.DestinationAddress() /* local */, eth.Type() /* protocol */, pkt)
    56  }
    57  
    58  // Capabilities implements stack.LinkEndpoint.
    59  func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
    60  	return stack.CapabilityResolutionRequired | e.Endpoint.Capabilities()
    61  }
    62  
    63  // WritePacket implements stack.LinkEndpoint.
    64  func (e *Endpoint) WritePacket(r stack.RouteInfo, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
    65  	e.AddHeader(e.Endpoint.LinkAddress(), r.RemoteLinkAddress, proto, pkt)
    66  	return e.Endpoint.WritePacket(r, proto, pkt)
    67  }
    68  
    69  // WritePackets implements stack.LinkEndpoint.
    70  func (e *Endpoint) WritePackets(r stack.RouteInfo, pkts stack.PacketBufferList, proto tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
    71  	linkAddr := e.Endpoint.LinkAddress()
    72  
    73  	for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() {
    74  		e.AddHeader(linkAddr, r.RemoteLinkAddress, proto, pkt)
    75  	}
    76  
    77  	return e.Endpoint.WritePackets(r, pkts, proto)
    78  }
    79  
    80  // MaxHeaderLength implements stack.LinkEndpoint.
    81  func (e *Endpoint) MaxHeaderLength() uint16 {
    82  	return header.EthernetMinimumSize + e.Endpoint.MaxHeaderLength()
    83  }
    84  
    85  // ARPHardwareType implements stack.LinkEndpoint.
    86  func (*Endpoint) ARPHardwareType() header.ARPHardwareType {
    87  	return header.ARPHardwareEther
    88  }
    89  
    90  // AddHeader implements stack.LinkEndpoint.
    91  func (*Endpoint) AddHeader(local, remote tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
    92  	eth := header.Ethernet(pkt.LinkHeader().Push(header.EthernetMinimumSize))
    93  	fields := header.EthernetFields{
    94  		SrcAddr: local,
    95  		DstAddr: remote,
    96  		Type:    proto,
    97  	}
    98  	eth.Encode(&fields)
    99  }