summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/link/fdbased
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/link/fdbased')
-rw-r--r--pkg/tcpip/link/fdbased/endpoint.go28
-rw-r--r--pkg/tcpip/link/fdbased/endpoint_test.go59
2 files changed, 60 insertions, 27 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go
index 40a10eb9b..ee99ada07 100644
--- a/pkg/tcpip/link/fdbased/endpoint.go
+++ b/pkg/tcpip/link/fdbased/endpoint.go
@@ -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.
diff --git a/pkg/tcpip/link/fdbased/endpoint_test.go b/pkg/tcpip/link/fdbased/endpoint_test.go
index 411ad7832..52e532ebb 100644
--- a/pkg/tcpip/link/fdbased/endpoint_test.go
+++ b/pkg/tcpip/link/fdbased/endpoint_test.go
@@ -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}