mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Pass local link address to DeliverNetworkPacket
This allows a NetworkDispatcher to implement transparent bridging, assuming all implementations of LinkEndpoint.WritePacket call eth.Encode with header.EthernetFields.SrcAddr set to the passed Route.LocalLinkAddress, if it is provided. PiperOrigin-RevId: 213686651 Change-Id: I446a4ac070970202f0724ef796ff1056ae4dd72a
This commit is contained in:
committed by
Shentubot
parent
f0a92b6b67
commit
2e497de2d9
@@ -72,7 +72,7 @@ func (e *Endpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.Vector
|
||||
|
||||
// InjectLinkAddr injects an inbound packet with a remote link address.
|
||||
func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remoteLinkAddr tcpip.LinkAddress, vv buffer.VectorisedView) {
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, protocol, vv.Clone(nil))
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, "" /* localLinkAddr */, protocol, vv.Clone(nil))
|
||||
}
|
||||
|
||||
// Attach saves the stack network-layer dispatcher for use later when packets
|
||||
|
||||
@@ -164,17 +164,24 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload b
|
||||
views[0] = hdr.View()
|
||||
views = append(views, payload.Views()...)
|
||||
vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
|
||||
e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, protocol, vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, r.LocalLinkAddress, protocol, vv)
|
||||
return nil
|
||||
}
|
||||
if e.hdrSize > 0 {
|
||||
// Add ethernet header if needed.
|
||||
eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize))
|
||||
eth.Encode(&header.EthernetFields{
|
||||
ethHdr := &header.EthernetFields{
|
||||
DstAddr: r.RemoteLinkAddress,
|
||||
SrcAddr: e.addr,
|
||||
Type: protocol,
|
||||
})
|
||||
}
|
||||
|
||||
// Preserve the src address if it's set in the route.
|
||||
if r.LocalLinkAddress != "" {
|
||||
ethHdr.SrcAddr = r.LocalLinkAddress
|
||||
} else {
|
||||
ethHdr.SrcAddr = e.addr
|
||||
}
|
||||
eth.Encode(ethHdr)
|
||||
}
|
||||
|
||||
if payload.Size() == 0 {
|
||||
@@ -223,12 +230,15 @@ func (e *endpoint) dispatch(largeV buffer.View) (bool, *tcpip.Error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var p tcpip.NetworkProtocolNumber
|
||||
var addr tcpip.LinkAddress
|
||||
var (
|
||||
p tcpip.NetworkProtocolNumber
|
||||
remoteLinkAddr, localLinkAddr tcpip.LinkAddress
|
||||
)
|
||||
if e.hdrSize > 0 {
|
||||
eth := header.Ethernet(e.views[0])
|
||||
p = eth.Type()
|
||||
addr = eth.SourceAddress()
|
||||
remoteLinkAddr = eth.SourceAddress()
|
||||
localLinkAddr = eth.DestinationAddress()
|
||||
} else {
|
||||
// We don't get any indication of what the packet is, so try to guess
|
||||
// if it's an IPv4 or IPv6 packet.
|
||||
@@ -246,7 +256,7 @@ func (e *endpoint) dispatch(largeV buffer.View) (bool, *tcpip.Error) {
|
||||
vv := buffer.NewVectorisedView(n, e.views[:used])
|
||||
vv.TrimFront(e.hdrSize)
|
||||
|
||||
e.dispatcher.DeliverNetworkPacket(e, addr, p, vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, localLinkAddr, p, vv)
|
||||
|
||||
// Prepare e.views for another packet: release used views.
|
||||
for i := 0; i < used; i++ {
|
||||
@@ -287,7 +297,7 @@ func (e *InjectableEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
|
||||
|
||||
// Inject injects an inbound packet.
|
||||
func (e *InjectableEndpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, "" /* remoteLinkAddr */, "" /* localLinkAddr */, protocol, vv)
|
||||
}
|
||||
|
||||
// NewInjectable creates a new fd-based InjectableEndpoint.
|
||||
|
||||
@@ -31,6 +31,13 @@ import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
const (
|
||||
mtu = 1500
|
||||
laddr = tcpip.LinkAddress("\x11\x22\x33\x44\x55\x66")
|
||||
raddr = tcpip.LinkAddress("\x77\x88\x99\xaa\xbb\xcc")
|
||||
proto = 10
|
||||
)
|
||||
|
||||
type packetInfo struct {
|
||||
raddr tcpip.LinkAddress
|
||||
proto tcpip.NetworkProtocolNumber
|
||||
@@ -78,12 +85,11 @@ func (c *context) cleanup() {
|
||||
syscall.Close(c.fds[1])
|
||||
}
|
||||
|
||||
func (c *context) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (c *context) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, localLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
c.ch <- packetInfo{remoteLinkAddr, protocol, vv.ToView()}
|
||||
}
|
||||
|
||||
func TestNoEthernetProperties(t *testing.T) {
|
||||
const mtu = 1500
|
||||
c := newContext(t, &Options{MTU: mtu})
|
||||
defer c.cleanup()
|
||||
|
||||
@@ -97,7 +103,6 @@ func TestNoEthernetProperties(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEthernetProperties(t *testing.T) {
|
||||
const mtu = 1500
|
||||
c := newContext(t, &Options{EthernetHeader: true, MTU: mtu})
|
||||
defer c.cleanup()
|
||||
|
||||
@@ -111,7 +116,6 @@ func TestEthernetProperties(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddress(t *testing.T) {
|
||||
const mtu = 1500
|
||||
addrs := []tcpip.LinkAddress{"", "abc", "def"}
|
||||
for _, a := range addrs {
|
||||
t.Run(fmt.Sprintf("Address: %q", a), func(t *testing.T) {
|
||||
@@ -126,13 +130,6 @@ func TestAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWritePacket(t *testing.T) {
|
||||
const (
|
||||
mtu = 1500
|
||||
laddr = tcpip.LinkAddress("\x11\x22\x33\x44\x55\x66")
|
||||
raddr = tcpip.LinkAddress("\x77\x88\x99\xaa\xbb\xcc")
|
||||
proto = 10
|
||||
)
|
||||
|
||||
lengths := []int{0, 100, 1000}
|
||||
eths := []bool{true, false}
|
||||
|
||||
@@ -197,14 +194,40 @@ func TestWritePacket(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeliverPacket(t *testing.T) {
|
||||
const (
|
||||
mtu = 1500
|
||||
laddr = tcpip.LinkAddress("\x11\x22\x33\x44\x55\x66")
|
||||
raddr = tcpip.LinkAddress("\x77\x88\x99\xaa\xbb\xcc")
|
||||
proto = 10
|
||||
)
|
||||
func TestPreserveSrcAddress(t *testing.T) {
|
||||
baddr := tcpip.LinkAddress("\xcc\xbb\xaa\x77\x88\x99")
|
||||
|
||||
c := newContext(t, &Options{Address: laddr, MTU: mtu, EthernetHeader: true})
|
||||
defer c.cleanup()
|
||||
|
||||
// Set LocalLinkAddress in route to the value of the bridged address.
|
||||
r := &stack.Route{
|
||||
RemoteLinkAddress: raddr,
|
||||
LocalLinkAddress: baddr,
|
||||
}
|
||||
|
||||
// WritePacket panics given a prependable with anything less than
|
||||
// the minimum size of the ethernet header.
|
||||
hdr := buffer.NewPrependable(header.EthernetMinimumSize)
|
||||
if err := c.ep.WritePacket(r, hdr, buffer.VectorisedView{}, proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
|
||||
// Read from the FD, then compare with what we wrote.
|
||||
b := make([]byte, mtu)
|
||||
n, err := syscall.Read(c.fds[0], b)
|
||||
if err != nil {
|
||||
t.Fatalf("Read failed: %v", err)
|
||||
}
|
||||
b = b[:n]
|
||||
h := header.Ethernet(b)
|
||||
|
||||
if a := h.SourceAddress(); a != baddr {
|
||||
t.Fatalf("SourceAddress() = %v, want %v", a, baddr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeliverPacket(t *testing.T) {
|
||||
lengths := []int{100, 1000}
|
||||
eths := []bool{true, false}
|
||||
|
||||
|
||||
@@ -77,7 +77,11 @@ func (e *endpoint) WritePacket(_ *stack.Route, hdr buffer.Prependable, payload b
|
||||
views[0] = hdr.View()
|
||||
views = append(views, payload.Views()...)
|
||||
vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
|
||||
e.dispatcher.DeliverNetworkPacket(e, "", protocol, vv)
|
||||
|
||||
// Because we're immediately turning around and writing the packet back to the
|
||||
// rx path, we intentionally don't preserve the remote and local link
|
||||
// addresses from the stack.Route we're passed.
|
||||
e.dispatcher.DeliverNetworkPacket(e, "" /* remoteLinkAddr */, "" /* localLinkAddr */, protocol, vv)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -187,11 +187,16 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress {
|
||||
func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error {
|
||||
// Add the ethernet header here.
|
||||
eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize))
|
||||
eth.Encode(&header.EthernetFields{
|
||||
ethHdr := &header.EthernetFields{
|
||||
DstAddr: r.RemoteLinkAddress,
|
||||
SrcAddr: e.addr,
|
||||
Type: protocol,
|
||||
})
|
||||
}
|
||||
if r.LocalLinkAddress != "" {
|
||||
ethHdr.SrcAddr = r.LocalLinkAddress
|
||||
} else {
|
||||
ethHdr.SrcAddr = e.addr
|
||||
}
|
||||
eth.Encode(ethHdr)
|
||||
|
||||
v := payload.ToView()
|
||||
// Transmit the packet.
|
||||
@@ -248,7 +253,7 @@ func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) {
|
||||
|
||||
// Send packet up the stack.
|
||||
eth := header.Ethernet(b)
|
||||
d.DeliverNetworkPacket(e, eth.SourceAddress(), eth.Type(), buffer.View(b[header.EthernetMinimumSize:]).ToVectorisedView())
|
||||
d.DeliverNetworkPacket(e, eth.SourceAddress(), eth.DestinationAddress(), eth.Type(), buffer.View(b[header.EthernetMinimumSize:]).ToVectorisedView())
|
||||
}
|
||||
|
||||
// Clean state.
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package sharedmem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
@@ -129,10 +131,10 @@ func newTestContext(t *testing.T, mtu, bufferSize uint32, addr tcpip.LinkAddress
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *testContext) DeliverNetworkPacket(_ stack.LinkEndpoint, remoteAddr tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (c *testContext) DeliverNetworkPacket(_ stack.LinkEndpoint, remoteLinkAddr, localLinkAddr tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
c.mu.Lock()
|
||||
c.packets = append(c.packets, packetInfo{
|
||||
addr: remoteAddr,
|
||||
addr: remoteLinkAddr,
|
||||
proto: proto,
|
||||
vv: vv.Clone(nil),
|
||||
})
|
||||
@@ -259,62 +261,120 @@ func TestSimpleSend(t *testing.T) {
|
||||
}
|
||||
|
||||
for iters := 1000; iters > 0; iters-- {
|
||||
// Prepare and send packet.
|
||||
n := rand.Intn(10000)
|
||||
hdr := buffer.NewPrependable(n + int(c.ep.MaxHeaderLength()))
|
||||
hdrBuf := hdr.Prepend(n)
|
||||
randomFill(hdrBuf)
|
||||
func() {
|
||||
// Prepare and send packet.
|
||||
n := rand.Intn(10000)
|
||||
hdr := buffer.NewPrependable(n + int(c.ep.MaxHeaderLength()))
|
||||
hdrBuf := hdr.Prepend(n)
|
||||
randomFill(hdrBuf)
|
||||
|
||||
n = rand.Intn(10000)
|
||||
buf := buffer.NewView(n)
|
||||
randomFill(buf)
|
||||
n = rand.Intn(10000)
|
||||
buf := buffer.NewView(n)
|
||||
randomFill(buf)
|
||||
|
||||
proto := tcpip.NetworkProtocolNumber(rand.Intn(0x10000))
|
||||
if err := c.ep.WritePacket(&r, hdr, buf.ToVectorisedView(), proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
proto := tcpip.NetworkProtocolNumber(rand.Intn(0x10000))
|
||||
if err := c.ep.WritePacket(&r, hdr, buf.ToVectorisedView(), proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
|
||||
// Receive packet.
|
||||
desc := c.txq.tx.Pull()
|
||||
pi := queue.DecodeTxPacketHeader(desc)
|
||||
contents := make([]byte, 0, pi.Size)
|
||||
for i := 0; i < pi.BufferCount; i++ {
|
||||
bi := queue.DecodeTxBufferHeader(desc, i)
|
||||
contents = append(contents, c.txq.data[bi.Offset:][:bi.Size]...)
|
||||
}
|
||||
c.txq.tx.Flush()
|
||||
// Receive packet.
|
||||
desc := c.txq.tx.Pull()
|
||||
pi := queue.DecodeTxPacketHeader(desc)
|
||||
if pi.Reserved != 0 {
|
||||
t.Fatalf("Reserved value is non-zero: 0x%x", pi.Reserved)
|
||||
}
|
||||
contents := make([]byte, 0, pi.Size)
|
||||
for i := 0; i < pi.BufferCount; i++ {
|
||||
bi := queue.DecodeTxBufferHeader(desc, i)
|
||||
contents = append(contents, c.txq.data[bi.Offset:][:bi.Size]...)
|
||||
}
|
||||
c.txq.tx.Flush()
|
||||
|
||||
if pi.Reserved != 0 {
|
||||
t.Fatalf("Reserved value is non-zero: 0x%x", pi.Reserved)
|
||||
}
|
||||
defer func() {
|
||||
// Tell the endpoint about the completion of the write.
|
||||
b := c.txq.rx.Push(8)
|
||||
queue.EncodeTxCompletion(b, pi.ID)
|
||||
c.txq.rx.Flush()
|
||||
}()
|
||||
|
||||
// Check the thernet header.
|
||||
ethTemplate := make(header.Ethernet, header.EthernetMinimumSize)
|
||||
ethTemplate.Encode(&header.EthernetFields{
|
||||
SrcAddr: localLinkAddr,
|
||||
DstAddr: remoteLinkAddr,
|
||||
Type: proto,
|
||||
})
|
||||
if got := contents[:header.EthernetMinimumSize]; !reflect.DeepEqual(got, []byte(ethTemplate)) {
|
||||
t.Fatalf("Bad ethernet header in packet: got %x, want %x", got, ethTemplate)
|
||||
}
|
||||
// Check the ethernet header.
|
||||
ethTemplate := make(header.Ethernet, header.EthernetMinimumSize)
|
||||
ethTemplate.Encode(&header.EthernetFields{
|
||||
SrcAddr: localLinkAddr,
|
||||
DstAddr: remoteLinkAddr,
|
||||
Type: proto,
|
||||
})
|
||||
if got := contents[:header.EthernetMinimumSize]; !bytes.Equal(got, []byte(ethTemplate)) {
|
||||
t.Fatalf("Bad ethernet header in packet: got %x, want %x", got, ethTemplate)
|
||||
}
|
||||
|
||||
// Compare contents skipping the ethernet header added by the
|
||||
// endpoint.
|
||||
merged := append(hdrBuf, buf...)
|
||||
if uint32(len(contents)) < pi.Size {
|
||||
t.Fatalf("Sum of buffers is less than packet size: %v < %v", len(contents), pi.Size)
|
||||
}
|
||||
contents = contents[:pi.Size][header.EthernetMinimumSize:]
|
||||
// Compare contents skipping the ethernet header added by the
|
||||
// endpoint.
|
||||
merged := append(hdrBuf, buf...)
|
||||
if uint32(len(contents)) < pi.Size {
|
||||
t.Fatalf("Sum of buffers is less than packet size: %v < %v", len(contents), pi.Size)
|
||||
}
|
||||
contents = contents[:pi.Size][header.EthernetMinimumSize:]
|
||||
|
||||
if !reflect.DeepEqual(contents, merged) {
|
||||
t.Fatalf("Buffers are different: got %x (%v bytes), want %x (%v bytes)", contents, len(contents), merged, len(merged))
|
||||
}
|
||||
if !bytes.Equal(contents, merged) {
|
||||
t.Fatalf("Buffers are different: got %x (%v bytes), want %x (%v bytes)", contents, len(contents), merged, len(merged))
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// TestPreserveSrcAddressInSend calls WritePacket once with LocalLinkAddress
|
||||
// set in Route (using much of the same code as TestSimpleSend), then checks
|
||||
// that the encoded ethernet header received includes the correct SrcAddr.
|
||||
func TestPreserveSrcAddressInSend(t *testing.T) {
|
||||
c := newTestContext(t, 20000, 1500, localLinkAddr)
|
||||
defer c.cleanup()
|
||||
|
||||
newLocalLinkAddress := tcpip.LinkAddress(strings.Repeat("0xFE", 6))
|
||||
// Set both remote and local link address in route.
|
||||
r := stack.Route{
|
||||
RemoteLinkAddress: remoteLinkAddr,
|
||||
LocalLinkAddress: newLocalLinkAddress,
|
||||
}
|
||||
|
||||
// WritePacket panics given a prependable with anything less than
|
||||
// the minimum size of the ethernet header.
|
||||
hdr := buffer.NewPrependable(header.EthernetMinimumSize)
|
||||
|
||||
proto := tcpip.NetworkProtocolNumber(rand.Intn(0x10000))
|
||||
if err := c.ep.WritePacket(&r, hdr, buffer.VectorisedView{}, proto); err != nil {
|
||||
t.Fatalf("WritePacket failed: %v", err)
|
||||
}
|
||||
|
||||
// Receive packet.
|
||||
desc := c.txq.tx.Pull()
|
||||
pi := queue.DecodeTxPacketHeader(desc)
|
||||
if pi.Reserved != 0 {
|
||||
t.Fatalf("Reserved value is non-zero: 0x%x", pi.Reserved)
|
||||
}
|
||||
contents := make([]byte, 0, pi.Size)
|
||||
for i := 0; i < pi.BufferCount; i++ {
|
||||
bi := queue.DecodeTxBufferHeader(desc, i)
|
||||
contents = append(contents, c.txq.data[bi.Offset:][:bi.Size]...)
|
||||
}
|
||||
c.txq.tx.Flush()
|
||||
|
||||
defer func() {
|
||||
// Tell the endpoint about the completion of the write.
|
||||
b := c.txq.rx.Push(8)
|
||||
queue.EncodeTxCompletion(b, pi.ID)
|
||||
c.txq.rx.Flush()
|
||||
}()
|
||||
|
||||
// Check that the ethernet header contains the expected SrcAddr.
|
||||
ethTemplate := make(header.Ethernet, header.EthernetMinimumSize)
|
||||
ethTemplate.Encode(&header.EthernetFields{
|
||||
SrcAddr: newLocalLinkAddress,
|
||||
DstAddr: remoteLinkAddr,
|
||||
Type: proto,
|
||||
})
|
||||
if got := contents[:header.EthernetMinimumSize]; !bytes.Equal(got, []byte(ethTemplate)) {
|
||||
t.Fatalf("Bad ethernet header in packet: got %x, want %x", got, ethTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +643,7 @@ func TestSimpleReceive(t *testing.T) {
|
||||
c.mu.Unlock()
|
||||
|
||||
contents = contents[header.EthernetMinimumSize:]
|
||||
if !reflect.DeepEqual(contents, rcvd) {
|
||||
if !bytes.Equal(contents, rcvd) {
|
||||
t.Fatalf("Unexpected buffer contents: got %x, want %x", rcvd, contents)
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ func NewWithFile(lower tcpip.LinkEndpointID, file *os.File, snapLen uint32) (tcp
|
||||
// DeliverNetworkPacket implements the stack.NetworkDispatcher interface. It is
|
||||
// called by the link-layer endpoint being wrapped when a packet arrives, and
|
||||
// logs the packet before forwarding to the actual dispatcher.
|
||||
func (e *endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (e *endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr, localLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
if atomic.LoadUint32(&LogPackets) == 1 && e.file == nil {
|
||||
logPacket("recv", protocol, vv.First())
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (e *endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAdd
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, protocol, vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, localLinkAddr, protocol, vv)
|
||||
}
|
||||
|
||||
// Attach implements the stack.LinkEndpoint interface. It saves the dispatcher
|
||||
|
||||
@@ -51,12 +51,12 @@ func New(lower tcpip.LinkEndpointID) (tcpip.LinkEndpointID, *Endpoint) {
|
||||
// It is called by the link-layer endpoint being wrapped when a packet arrives,
|
||||
// and only forwards to the actual dispatcher if Wait or WaitDispatch haven't
|
||||
// been called.
|
||||
func (e *Endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (e *Endpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr, localLinkAddress tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
if !e.dispatchGate.Enter() {
|
||||
return
|
||||
}
|
||||
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, protocol, vv)
|
||||
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, localLinkAddress, protocol, vv)
|
||||
e.dispatchGate.Leave()
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ type countedEndpoint struct {
|
||||
dispatcher stack.NetworkDispatcher
|
||||
}
|
||||
|
||||
func (e *countedEndpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (e *countedEndpoint) DeliverNetworkPacket(linkEP stack.LinkEndpoint, remoteLinkAddr, localLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
e.dispatchCount++
|
||||
}
|
||||
|
||||
@@ -106,21 +106,21 @@ func TestWaitDispatch(t *testing.T) {
|
||||
}
|
||||
|
||||
// Dispatch and check that it goes through.
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", "", 0, buffer.VectorisedView{})
|
||||
if want := 1; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
// Wait on writes, then try to dispatch. It must go through.
|
||||
wep.WaitWrite()
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", "", 0, buffer.VectorisedView{})
|
||||
if want := 2; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
// Wait on dispatches, then try to dispatch. It must not go through.
|
||||
wep.WaitDispatch()
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", 0, buffer.VectorisedView{})
|
||||
ep.dispatcher.DeliverNetworkPacket(ep, "", "", 0, buffer.VectorisedView{})
|
||||
if want := 2; ep.dispatchCount != want {
|
||||
t.Fatalf("Unexpected dispatchCount: got=%v, want=%v", ep.dispatchCount, want)
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ func (n *NIC) RemoveAddress(addr tcpip.Address) *tcpip.Error {
|
||||
// Note that the ownership of the slice backing vv is retained by the caller.
|
||||
// This rule applies only to the slice itself, not to the items of the slice;
|
||||
// the ownership of the items is not retained by the caller.
|
||||
func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr, localLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
|
||||
netProto, ok := n.stack.networkProtocols[protocol]
|
||||
if !ok {
|
||||
n.stack.stats.UnknownProtocolRcvdPackets.Increment()
|
||||
|
||||
@@ -196,7 +196,7 @@ type NetworkProtocol interface {
|
||||
type NetworkDispatcher interface {
|
||||
// DeliverNetworkPacket finds the appropriate network protocol
|
||||
// endpoint and hands the packet over for further processing.
|
||||
DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView)
|
||||
DeliverNetworkPacket(linkEP LinkEndpoint, dstLinkAddr, srcLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView)
|
||||
}
|
||||
|
||||
// LinkEndpointCapabilities is the type associated with the capabilities
|
||||
@@ -238,6 +238,10 @@ type LinkEndpoint interface {
|
||||
|
||||
// WritePacket writes a packet with the given protocol through the given
|
||||
// route.
|
||||
//
|
||||
// To participate in transparent bridging, a LinkEndpoint implementation
|
||||
// should call eth.Encode with header.EthernetFields.SrcAddr set to
|
||||
// r.LocalLinkAddress if it is provided.
|
||||
WritePacket(r *Route, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.NetworkProtocolNumber) *tcpip.Error
|
||||
|
||||
// Attach attaches the data link layer endpoint to the network-layer
|
||||
|
||||
Reference in New Issue
Block a user