github.com/noisysockets/netstack@v0.6.0/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/noisysockets/netstack/pkg/tcpip"
    21  	"github.com/noisysockets/netstack/pkg/tcpip/header"
    22  	"github.com/noisysockets/netstack/pkg/tcpip/link/nested"
    23  	"github.com/noisysockets/netstack/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  // LinkAddress implements stack.LinkEndpoint.
    46  func (e *Endpoint) LinkAddress() tcpip.LinkAddress {
    47  	if l := e.Endpoint.LinkAddress(); len(l) != 0 {
    48  		return l
    49  	}
    50  	return header.UnspecifiedEthernetAddress
    51  }
    52  
    53  // MTU implements stack.LinkEndpoint.
    54  func (e *Endpoint) MTU() uint32 {
    55  	if mtu := e.Endpoint.MTU(); mtu > header.EthernetMinimumSize {
    56  		return mtu - header.EthernetMinimumSize
    57  	}
    58  	return 0
    59  }
    60  
    61  // DeliverNetworkPacket implements stack.NetworkDispatcher.
    62  func (e *Endpoint) DeliverNetworkPacket(_ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
    63  	if !e.ParseHeader(pkt) {
    64  		return
    65  	}
    66  	eth := header.Ethernet(pkt.LinkHeader().Slice())
    67  	dst := eth.DestinationAddress()
    68  	if dst == header.EthernetBroadcastAddress {
    69  		pkt.PktType = tcpip.PacketBroadcast
    70  	} else if header.IsMulticastEthernetAddress(dst) {
    71  		pkt.PktType = tcpip.PacketMulticast
    72  	} else if dst == e.LinkAddress() {
    73  		pkt.PktType = tcpip.PacketHost
    74  	} else {
    75  		pkt.PktType = tcpip.PacketOtherHost
    76  	}
    77  
    78  	// Note, there is no need to check the destination link address here since
    79  	// the ethernet hardware filters frames based on their destination addresses.
    80  	e.Endpoint.DeliverNetworkPacket(eth.Type() /* protocol */, pkt)
    81  }
    82  
    83  // Capabilities implements stack.LinkEndpoint.
    84  func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
    85  	c := e.Endpoint.Capabilities()
    86  	if c&stack.CapabilityLoopback == 0 {
    87  		c |= stack.CapabilityResolutionRequired
    88  	}
    89  	return c
    90  }
    91  
    92  // MaxHeaderLength implements stack.LinkEndpoint.
    93  func (e *Endpoint) MaxHeaderLength() uint16 {
    94  	return header.EthernetMinimumSize + e.Endpoint.MaxHeaderLength()
    95  }
    96  
    97  // ARPHardwareType implements stack.LinkEndpoint.
    98  func (e *Endpoint) ARPHardwareType() header.ARPHardwareType {
    99  	if a := e.Endpoint.ARPHardwareType(); a != header.ARPHardwareNone {
   100  		return a
   101  	}
   102  	return header.ARPHardwareEther
   103  }
   104  
   105  // AddHeader implements stack.LinkEndpoint.
   106  func (*Endpoint) AddHeader(pkt *stack.PacketBuffer) {
   107  	eth := header.Ethernet(pkt.LinkHeader().Push(header.EthernetMinimumSize))
   108  	fields := header.EthernetFields{
   109  		SrcAddr: pkt.EgressRoute.LocalLinkAddress,
   110  		DstAddr: pkt.EgressRoute.RemoteLinkAddress,
   111  		Type:    pkt.NetworkProtocolNumber,
   112  	}
   113  	eth.Encode(&fields)
   114  }
   115  
   116  // ParseHeader implements stack.LinkEndpoint.
   117  func (*Endpoint) ParseHeader(pkt *stack.PacketBuffer) bool {
   118  	_, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
   119  	return ok
   120  }