blob: d1a24e7f57a1602ecc52da4d47b2aaec520bd577 [file] [log] [blame] [edit]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// +build !build_with_native_toolchain
package eth
import (
"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/eth/utils"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/nested"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ stack.LinkEndpoint = (*endpoint)(nil)
var _ stack.GSOEndpoint = (*Client)(nil)
var _ stack.NetworkDispatcher = (*endpoint)(nil)
type endpoint struct {
nested.Endpoint
}
func (e *endpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityResolutionRequired | e.Endpoint.Capabilities()
}
func (e *endpoint) MaxHeaderLength() uint16 {
return header.EthernetMinimumSize
}
func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) *tcpip.Error {
if pkt.LinkHeader().View().IsEmpty() {
e.AddHeader(r.LocalLinkAddress, r.RemoteLinkAddress(), protocol, pkt)
}
return e.Endpoint.WritePacket(r, gso, protocol, pkt)
}
func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.PacketBufferList, protocol tcpip.NetworkProtocolNumber) (int, *tcpip.Error) {
fields := utils.MakeEthernetFields(e.LinkAddress(), r.LocalLinkAddress, r.RemoteLinkAddress(), protocol)
for pkt := pkts.Front(); pkt != nil; pkt = pkt.Next() {
if pkt.LinkHeader().View().IsEmpty() {
utils.AddEthernetHeaderWithFields(&fields, pkt)
}
}
return e.Endpoint.WritePackets(r, gso, pkts, protocol)
}
func (e *endpoint) DeliverNetworkPacket(dstLinkAddr, srcLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
ethBytes, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize)
if !ok {
// TODO(fxbug.dev/42949): record this in statistics.
return
}
eth := header.Ethernet(ethBytes)
if len(dstLinkAddr) == 0 {
dstLinkAddr = eth.SourceAddress()
}
if len(srcLinkAddr) == 0 {
srcLinkAddr = eth.DestinationAddress()
}
if protocol == 0 {
protocol = eth.Type()
}
e.Endpoint.DeliverNetworkPacket(dstLinkAddr, srcLinkAddr, protocol, pkt)
}
func (*endpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareEther
}
func (e *endpoint) AddHeader(local, remote tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
utils.AddEthernetHeader(e.LinkAddress(), local, remote, protocol, pkt)
}
func NewLinkEndpoint(ep stack.LinkEndpoint) *endpoint {
e := &endpoint{}
e.Endpoint.Init(ep, e)
return e
}