// Copyright 2022 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package packetsocket_test import ( "math" "os" "testing" "gvisor.dev/gvisor/pkg/refs" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/packetsocket" "gvisor.dev/gvisor/pkg/tcpip/stack" ) var _ stack.LinkEndpoint = (*nullEndpoint)(nil) type nullEndpoint struct { disp stack.NetworkDispatcher } func (*nullEndpoint) MTU() uint32 { return math.MaxUint32 } func (*nullEndpoint) SetMTU(uint32) {} func (*nullEndpoint) Capabilities() stack.LinkEndpointCapabilities { return 0 } func (*nullEndpoint) MaxHeaderLength() uint16 { return 0 } func (*nullEndpoint) LinkAddress() tcpip.LinkAddress { return "" } func (*nullEndpoint) SetLinkAddress(tcpip.LinkAddress) { } func (*nullEndpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) { return pkts.Len(), nil } func (e *nullEndpoint) Attach(d stack.NetworkDispatcher) { e.disp = d } func (e *nullEndpoint) IsAttached() bool { return e.disp != nil } func (*nullEndpoint) Wait() {} func (*nullEndpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone } func (*nullEndpoint) AddHeader(*stack.PacketBuffer) {} func (*nullEndpoint) ParseHeader(*stack.PacketBuffer) bool { return true } func (*nullEndpoint) Close() {} func (*nullEndpoint) SetOnCloseAction(func()) {} var _ stack.NetworkDispatcher = (*testNetworkDispatcher)(nil) type linkPacketInfo struct { pkt *stack.PacketBuffer protocol tcpip.NetworkProtocolNumber } type networkPacketInfo struct { pkt *stack.PacketBuffer protocol tcpip.NetworkProtocolNumber } type testNetworkDispatcher struct { t *testing.T linkPacket linkPacketInfo networkPacket networkPacketInfo } func (t *testNetworkDispatcher) reset() { if pkt := t.linkPacket.pkt; pkt != nil { pkt.DecRef() } if pkt := t.networkPacket.pkt; pkt != nil { pkt.DecRef() } *t = testNetworkDispatcher{} } func (t *testNetworkDispatcher) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { networkPacket := networkPacketInfo{ pkt: pkt.IncRef(), protocol: protocol, } if t.networkPacket != (networkPacketInfo{}) { t.t.Fatalf("already delivered network packet = %#v; new = %#v", t.networkPacket, networkPacket) } t.networkPacket = networkPacket } func (t *testNetworkDispatcher) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { linkPacket := linkPacketInfo{ pkt: pkt.IncRef(), protocol: protocol, } if t.linkPacket != (linkPacketInfo{}) { t.t.Fatalf("already delivered link packet = %#v; new = %#v", t.linkPacket, linkPacket) } t.linkPacket = linkPacket } func TestPacketDispatch(t *testing.T) { const protocol = 5 var nullEP nullEndpoint ep := packetsocket.New(&nullEP) var d testNetworkDispatcher defer d.reset() ep.Attach(&d) pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{}) defer pkt.DecRef() pkt.NetworkProtocolNumber = protocol { pkt.PktType = tcpip.PacketOutgoing var pkts stack.PacketBufferList pkts.PushBack(pkt) if n, err := ep.WritePackets(pkts); err != nil { t.Fatalf("ep.WritePackets(_): %s", err) } else if n != 1 { t.Fatalf("got ep.WritePackets(_) = %d, want = 1", n) } if want := (networkPacketInfo{}); d.networkPacket != want { t.Errorf("got d.networkPacket = %#v, want = %#v", d.networkPacket, want) } if want := (linkPacketInfo{pkt: pkt, protocol: protocol}); d.linkPacket != want { t.Errorf("got d.linkPacket = %#v, want = %#v", d.linkPacket, want) } } d.reset() { pkt.PktType = tcpip.PacketHost nullEP.disp.DeliverNetworkPacket(protocol, pkt) if want := (networkPacketInfo{pkt: pkt, protocol: protocol}); d.networkPacket != want { t.Errorf("got d.networkPacket = %#v, want = %#v", d.networkPacket, want) } if want := (linkPacketInfo{pkt: pkt, protocol: protocol}); d.linkPacket != want { t.Errorf("got d.linkPacket = %#v, want = %#v", d.linkPacket, want) } } } func TestMain(m *testing.M) { refs.SetLeakMode(refs.LeaksPanic) code := m.Run() refs.DoLeakCheck() os.Exit(code) }