mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Set PktType for all Ethernet Packets
In preparation for improving ARP handling of gratuitous ARPs, set PktType in regular inbound flow instead of only when handling packet sockets. PiperOrigin-RevId: 501562322
This commit is contained in:
@@ -26,5 +26,6 @@ go_test(
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/link/channel",
|
||||
"//pkg/tcpip/stack",
|
||||
"@com_github_google_go_cmp//cmp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -64,10 +64,21 @@ func (e *Endpoint) DeliverNetworkPacket(_ tcpip.NetworkProtocolNumber, pkt stack
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
eth := header.Ethernet(hdr)
|
||||
dst := eth.DestinationAddress()
|
||||
if dst == header.EthernetBroadcastAddress {
|
||||
pkt.PktType = tcpip.PacketBroadcast
|
||||
} else if header.IsMulticastEthernetAddress(dst) {
|
||||
pkt.PktType = tcpip.PacketMulticast
|
||||
} else if dst == e.LinkAddress() {
|
||||
pkt.PktType = tcpip.PacketHost
|
||||
} else {
|
||||
pkt.PktType = tcpip.PacketOtherHost
|
||||
}
|
||||
|
||||
// Note, there is no need to check the destination link address here since
|
||||
// the ethernet hardware filters frames based on their destination addresses.
|
||||
e.Endpoint.DeliverNetworkPacket(header.Ethernet(hdr).Type() /* protocol */, pkt)
|
||||
e.Endpoint.DeliverNetworkPacket(eth.Type() /* protocol */, pkt)
|
||||
}
|
||||
|
||||
// Capabilities implements stack.LinkEndpoint.
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gvisor.dev/gvisor/pkg/bufferv2"
|
||||
"gvisor.dev/gvisor/pkg/refs"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
@@ -30,47 +31,94 @@ import (
|
||||
|
||||
var _ stack.NetworkDispatcher = (*testNetworkDispatcher)(nil)
|
||||
|
||||
type deliveredPacket struct {
|
||||
protocol tcpip.NetworkProtocolNumber
|
||||
packet stack.PacketBufferPtr
|
||||
}
|
||||
|
||||
type testNetworkDispatcher struct {
|
||||
networkPackets int
|
||||
networkPackets []deliveredPacket
|
||||
}
|
||||
|
||||
func (t *testNetworkDispatcher) DeliverNetworkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
t.networkPackets++
|
||||
func (t *testNetworkDispatcher) DeliverNetworkPacket(proto tcpip.NetworkProtocolNumber, pb stack.PacketBufferPtr) {
|
||||
t.networkPackets = append(t.networkPackets, deliveredPacket{protocol: proto, packet: pb})
|
||||
}
|
||||
|
||||
func (*testNetworkDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (*testNetworkDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func TestDeliverNetworkPacket(t *testing.T) {
|
||||
|
||||
const (
|
||||
linkAddr = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x06")
|
||||
otherLinkAddr1 = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x07")
|
||||
otherLinkAddr2 = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x08")
|
||||
linkAddr = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x06")
|
||||
otherLinkAddr = tcpip.LinkAddress("\x02\x02\x03\x04\x05\x07")
|
||||
)
|
||||
|
||||
e := ethernet.New(channel.New(0, 0, linkAddr))
|
||||
var networkDispatcher testNetworkDispatcher
|
||||
e.Attach(&networkDispatcher)
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
dstAddr tcpip.LinkAddress
|
||||
pktType tcpip.PacketType
|
||||
}{
|
||||
{
|
||||
name: "unicast",
|
||||
dstAddr: linkAddr,
|
||||
pktType: tcpip.PacketHost,
|
||||
},
|
||||
{
|
||||
name: "broadcast",
|
||||
dstAddr: header.EthernetBroadcastAddress,
|
||||
pktType: tcpip.PacketBroadcast,
|
||||
},
|
||||
{
|
||||
name: "multicast",
|
||||
dstAddr: tcpip.LinkAddress("\xFF\x00\x00\x00\x05\x07"),
|
||||
pktType: tcpip.PacketMulticast,
|
||||
},
|
||||
{
|
||||
name: "other host",
|
||||
dstAddr: tcpip.LinkAddress("\x02\x02\x03\x04\x05\x08"),
|
||||
pktType: tcpip.PacketOtherHost,
|
||||
},
|
||||
} {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
|
||||
if networkDispatcher.networkPackets != 0 {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = 0", networkDispatcher.networkPackets)
|
||||
}
|
||||
e := ethernet.New(channel.New(0, 0, linkAddr))
|
||||
var networkDispatcher testNetworkDispatcher
|
||||
e.Attach(&networkDispatcher)
|
||||
|
||||
// An ethernet frame with a destination link address that is not assigned to
|
||||
// our ethernet link endpoint should still be delivered to the network
|
||||
// dispatcher since the ethernet endpoint is not expected to filter frames.
|
||||
eth := make([]byte, header.EthernetMinimumSize)
|
||||
header.Ethernet(eth).Encode(&header.EthernetFields{
|
||||
SrcAddr: otherLinkAddr1,
|
||||
DstAddr: otherLinkAddr2,
|
||||
Type: header.IPv4ProtocolNumber,
|
||||
})
|
||||
p := stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: bufferv2.MakeWithData(eth)})
|
||||
defer p.DecRef()
|
||||
e.DeliverNetworkPacket(0, p)
|
||||
if networkDispatcher.networkPackets != 1 {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = 1", networkDispatcher.networkPackets)
|
||||
if got, want := len(networkDispatcher.networkPackets), 0; got != want {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = %d", got, want)
|
||||
}
|
||||
|
||||
const networkProtocol = header.IPv4ProtocolNumber
|
||||
|
||||
// An ethernet frame with a destination link address that is not assigned to
|
||||
// our ethernet link endpoint should still be delivered to the network
|
||||
// dispatcher since the ethernet endpoint is not expected to filter frames.
|
||||
eth := make([]byte, header.EthernetMinimumSize)
|
||||
header.Ethernet(eth).Encode(&header.EthernetFields{
|
||||
SrcAddr: otherLinkAddr,
|
||||
DstAddr: testCase.dstAddr,
|
||||
Type: networkProtocol,
|
||||
})
|
||||
p := stack.NewPacketBuffer(stack.PacketBufferOptions{Payload: bufferv2.MakeWithData(eth)})
|
||||
defer p.DecRef()
|
||||
e.DeliverNetworkPacket(0, p)
|
||||
if got, want := len(networkDispatcher.networkPackets), 1; got != want {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = %d", got, want)
|
||||
}
|
||||
delivered := networkDispatcher.networkPackets[0]
|
||||
if diff := cmp.Diff(delivered.packet.LinkHeader().Slice(), eth); diff != "" {
|
||||
t.Errorf("LinkHeader mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
if got, want := delivered.protocol, networkProtocol; got != want {
|
||||
t.Errorf("got delivered.protocol = %d, want = %d", got, want)
|
||||
}
|
||||
if got, want := delivered.packet.PktType, testCase.pktType; got != want {
|
||||
t.Errorf("got delivered.packet.PktType = %d, want = %d", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ func (c *context) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt
|
||||
c.ch <- packetInfo{protocol, pkt}
|
||||
}
|
||||
|
||||
func (c *context) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (c *context) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
c.t.Fatal("DeliverLinkPacket not implemented")
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ func (d *fakeNetworkDispatcher) DeliverNetworkPacket(_ tcpip.NetworkProtocolNumb
|
||||
d.pkts = append(d.pkts, pkt)
|
||||
}
|
||||
|
||||
func (*fakeNetworkDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (*fakeNetworkDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
|
||||
@@ -61,12 +61,12 @@ func (e *Endpoint) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pk
|
||||
}
|
||||
|
||||
// DeliverLinkPacket implements stack.NetworkDispatcher.
|
||||
func (e *Endpoint) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr, incoming bool) {
|
||||
func (e *Endpoint) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
|
||||
e.mu.RLock()
|
||||
d := e.dispatcher
|
||||
e.mu.RUnlock()
|
||||
if d != nil {
|
||||
d.DeliverLinkPacket(protocol, pkt, incoming)
|
||||
d.DeliverLinkPacket(protocol, pkt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ func (d *counterDispatcher) DeliverNetworkPacket(tcpip.NetworkProtocolNumber, st
|
||||
d.count++
|
||||
}
|
||||
|
||||
func (*counterDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (*counterDispatcher) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ func New(lower stack.LinkEndpoint) stack.LinkEndpoint {
|
||||
|
||||
// DeliverNetworkPacket implements stack.NetworkDispatcher.
|
||||
func (e *endpoint) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
|
||||
e.Endpoint.DeliverLinkPacket(protocol, pkt, true /* incoming */)
|
||||
e.Endpoint.DeliverLinkPacket(protocol, pkt)
|
||||
|
||||
e.Endpoint.DeliverNetworkPacket(protocol, pkt)
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func (e *endpoint) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pk
|
||||
// WritePackets implements stack.LinkEndpoint.
|
||||
func (e *endpoint) WritePackets(pkts stack.PacketBufferList) (int, tcpip.Error) {
|
||||
for _, pkt := range pkts.AsSlice() {
|
||||
e.Endpoint.DeliverLinkPacket(pkt.NetworkProtocolNumber, pkt, false /* incoming */)
|
||||
e.Endpoint.DeliverLinkPacket(pkt.NetworkProtocolNumber, pkt)
|
||||
}
|
||||
|
||||
return e.Endpoint.WritePackets(pkts)
|
||||
|
||||
@@ -59,7 +59,6 @@ var _ stack.NetworkDispatcher = (*testNetworkDispatcher)(nil)
|
||||
type linkPacketInfo struct {
|
||||
pkt stack.PacketBufferPtr
|
||||
protocol tcpip.NetworkProtocolNumber
|
||||
incoming bool
|
||||
}
|
||||
|
||||
type networkPacketInfo struct {
|
||||
@@ -99,11 +98,10 @@ func (t *testNetworkDispatcher) DeliverNetworkPacket(protocol tcpip.NetworkProto
|
||||
t.networkPacket = networkPacket
|
||||
}
|
||||
|
||||
func (t *testNetworkDispatcher) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr, incoming bool) {
|
||||
func (t *testNetworkDispatcher) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
|
||||
linkPacket := linkPacketInfo{
|
||||
pkt: pkt.IncRef(),
|
||||
protocol: protocol,
|
||||
incoming: incoming,
|
||||
}
|
||||
|
||||
if t.linkPacket != (linkPacketInfo{}) {
|
||||
@@ -128,6 +126,7 @@ func TestPacketDispatch(t *testing.T) {
|
||||
pkt.NetworkProtocolNumber = protocol
|
||||
|
||||
{
|
||||
pkt.PktType = tcpip.PacketOutgoing
|
||||
var pkts stack.PacketBufferList
|
||||
pkts.PushBack(pkt)
|
||||
if n, err := ep.WritePackets(pkts); err != nil {
|
||||
@@ -139,18 +138,19 @@ func TestPacketDispatch(t *testing.T) {
|
||||
if want := (networkPacketInfo{}); d.networkPacket != want {
|
||||
t.Errorf("got d.networkPacket = %#v, want = %#v", d.networkPacket, want)
|
||||
}
|
||||
if want := (linkPacketInfo{pkt: pkt, protocol: protocol, incoming: false}); d.linkPacket != 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, incoming: true}); d.linkPacket != want {
|
||||
if want := (linkPacketInfo{pkt: pkt, protocol: protocol}); d.linkPacket != want {
|
||||
t.Errorf("got d.linkPacket = %#v, want = %#v", d.linkPacket, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ func (c *testContext) DeliverNetworkPacket(proto tcpip.NetworkProtocolNumber, pk
|
||||
c.packetCh <- struct{}{}
|
||||
}
|
||||
|
||||
func (c *testContext) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (c *testContext) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
c.t.Fatal("DeliverLinkPacket not implemented")
|
||||
}
|
||||
|
||||
|
||||
@@ -63,12 +63,12 @@ func (e *Endpoint) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pk
|
||||
}
|
||||
|
||||
// DeliverLinkPacket implements stack.NetworkDispatcher.
|
||||
func (e *Endpoint) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr, incoming bool) {
|
||||
func (e *Endpoint) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) {
|
||||
if !e.dispatchGate.Enter() {
|
||||
return
|
||||
}
|
||||
|
||||
e.dispatcher.DeliverLinkPacket(protocol, pkt, incoming)
|
||||
e.dispatcher.DeliverLinkPacket(protocol, pkt)
|
||||
e.dispatchGate.Leave()
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ func (e *countedEndpoint) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNum
|
||||
e.dispatchCount++
|
||||
}
|
||||
|
||||
func (*countedEndpoint) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr, bool) {
|
||||
func (*countedEndpoint) DeliverLinkPacket(tcpip.NetworkProtocolNumber, stack.PacketBufferPtr) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -386,6 +386,8 @@ func (n *nic) writePacket(pkt PacketBufferPtr) tcpip.Error {
|
||||
}
|
||||
|
||||
func (n *nic) writeRawPacket(pkt PacketBufferPtr) tcpip.Error {
|
||||
// Always an outgoing packet.
|
||||
pkt.PktType = tcpip.PacketOutgoing
|
||||
if err := n.qDisc.WritePacket(pkt); err != nil {
|
||||
if _, ok := err.(*tcpip.ErrNoBufferSpace); ok {
|
||||
n.stats.txPacketsDroppedNoBufferSpace.Increment()
|
||||
@@ -738,7 +740,7 @@ func (n *nic) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt Pac
|
||||
n.gro.dispatch(pkt, protocol, networkEndpoint)
|
||||
}
|
||||
|
||||
func (n *nic) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt PacketBufferPtr, incoming bool) {
|
||||
func (n *nic) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt PacketBufferPtr) {
|
||||
// Deliver to interested packet endpoints without holding NIC lock.
|
||||
var packetEPPkt PacketBufferPtr
|
||||
defer func() {
|
||||
@@ -764,11 +766,13 @@ func (n *nic) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt Packet
|
||||
// populate it in the packet buffer we provide to packet endpoints as
|
||||
// packet endpoints inspect link headers.
|
||||
packetEPPkt.LinkHeader().Consume(len(pkt.LinkHeader().Slice()))
|
||||
|
||||
if incoming {
|
||||
packetEPPkt.PktType = pkt.PktType
|
||||
// Assume the packet is for us if the packet type is unset.
|
||||
// The packet type is set to PacketOutgoing when sending packets so
|
||||
// this may only be unset for incoming packets where link endpoints
|
||||
// have not set it.
|
||||
if packetEPPkt.PktType == 0 {
|
||||
packetEPPkt.PktType = tcpip.PacketHost
|
||||
} else {
|
||||
packetEPPkt.PktType = tcpip.PacketOutgoing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,7 +789,7 @@ func (n *nic) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt Packet
|
||||
n.packetEPsMu.Unlock()
|
||||
|
||||
// On Linux, only ETH_P_ALL endpoints get outbound packets.
|
||||
if incoming && protoEPsOK {
|
||||
if pkt.PktType != tcpip.PacketOutgoing && protoEPsOK {
|
||||
protoEPs.forEach(deliverPacketEPs)
|
||||
}
|
||||
if anyEPsOK {
|
||||
|
||||
@@ -1034,7 +1034,7 @@ type NetworkDispatcher interface {
|
||||
// This method should be called with both incoming and outgoing packets.
|
||||
//
|
||||
// If the link-layer has a header, the packet's link header must be populated.
|
||||
DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt PacketBufferPtr, incoming bool)
|
||||
DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt PacketBufferPtr)
|
||||
}
|
||||
|
||||
// LinkEndpointCapabilities is the type associated with the capabilities
|
||||
|
||||
Reference in New Issue
Block a user