mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Do not filter frames in ethernet link endpoint
Ethernet frames are usually filtered at the hardware-level so there is no need to filter the frames in software. For test purposes, a new link endpoint was introduced to filter frames based on their destination. PiperOrigin-RevId: 350422941
This commit is contained in:
committed by
gVisor bot
parent
abe9d9f67f
commit
7817e3b5e4
@@ -1,4 +1,4 @@
|
||||
load("//tools:defs.bzl", "go_library")
|
||||
load("//tools:defs.bzl", "go_library", "go_test")
|
||||
|
||||
package(licenses = ["notice"])
|
||||
|
||||
@@ -13,3 +13,17 @@ go_library(
|
||||
"//pkg/tcpip/stack",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "ethernet_test",
|
||||
size = "small",
|
||||
srcs = ["ethernet_test.go"],
|
||||
deps = [
|
||||
":ethernet",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/tcpip/buffer",
|
||||
"//pkg/tcpip/header",
|
||||
"//pkg/tcpip/link/channel",
|
||||
"//pkg/tcpip/stack",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -49,10 +49,10 @@ func (e *Endpoint) DeliverNetworkPacket(_, _ tcpip.LinkAddress, _ tcpip.NetworkP
|
||||
return
|
||||
}
|
||||
|
||||
// Note, there is no need to check the destination link address here since
|
||||
// the ethernet hardware filters frames based on their destination addresses.
|
||||
eth := header.Ethernet(hdr)
|
||||
if dst := eth.DestinationAddress(); dst == e.Endpoint.LinkAddress() || dst == header.EthernetBroadcastAddress || header.IsMulticastEthernetAddress(dst) {
|
||||
e.Endpoint.DeliverNetworkPacket(eth.SourceAddress() /* remote */, dst /* local */, eth.Type() /* protocol */, pkt)
|
||||
}
|
||||
e.Endpoint.DeliverNetworkPacket(eth.SourceAddress() /* remote */, eth.DestinationAddress() /* local */, eth.Type() /* protocol */, pkt)
|
||||
}
|
||||
|
||||
// Capabilities implements stack.LinkEndpoint.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2021 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 ethernet_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
var _ stack.NetworkDispatcher = (*testNetworkDispatcher)(nil)
|
||||
|
||||
type testNetworkDispatcher struct {
|
||||
networkPackets int
|
||||
}
|
||||
|
||||
func (t *testNetworkDispatcher) DeliverNetworkPacket(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, _ *stack.PacketBuffer) {
|
||||
t.networkPackets++
|
||||
}
|
||||
|
||||
func (*testNetworkDispatcher) DeliverOutboundPacket(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, _ *stack.PacketBuffer) {
|
||||
}
|
||||
|
||||
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")
|
||||
)
|
||||
|
||||
e := ethernet.New(channel.New(0, 0, linkAddr))
|
||||
var networkDispatcher testNetworkDispatcher
|
||||
e.Attach(&networkDispatcher)
|
||||
|
||||
if networkDispatcher.networkPackets != 0 {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = 0", networkDispatcher.networkPackets)
|
||||
}
|
||||
|
||||
// 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 := buffer.NewView(header.EthernetMinimumSize)
|
||||
header.Ethernet(eth).Encode(&header.EthernetFields{
|
||||
SrcAddr: otherLinkAddr1,
|
||||
DstAddr: otherLinkAddr2,
|
||||
Type: header.IPv4ProtocolNumber,
|
||||
})
|
||||
e.DeliverNetworkPacket("", "", 0, stack.NewPacketBuffer(stack.PacketBufferOptions{
|
||||
Data: eth.ToVectorisedView(),
|
||||
}))
|
||||
if networkDispatcher.networkPackets != 1 {
|
||||
t.Fatalf("got networkDispatcher.networkPackets = %d, want = 1", networkDispatcher.networkPackets)
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ go_test(
|
||||
"//pkg/tcpip/link/channel",
|
||||
"//pkg/tcpip/link/ethernet",
|
||||
"//pkg/tcpip/link/loopback",
|
||||
"//pkg/tcpip/link/nested",
|
||||
"//pkg/tcpip/link/pipe",
|
||||
"//pkg/tcpip/network/arp",
|
||||
"//pkg/tcpip/network/ipv4",
|
||||
|
||||
@@ -21,7 +21,9 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/nested"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/pipe"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
@@ -31,6 +33,33 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
var _ stack.NetworkDispatcher = (*endpointWithDestinationCheck)(nil)
|
||||
var _ stack.LinkEndpoint = (*endpointWithDestinationCheck)(nil)
|
||||
|
||||
// newEthernetEndpoint returns an ethernet link endpoint that wraps an inner
|
||||
// link endpoint and checks the destination link address before delivering
|
||||
// network packets to the network dispatcher.
|
||||
//
|
||||
// See ethernet.Endpoint for more details.
|
||||
func newEthernetEndpoint(ep stack.LinkEndpoint) *endpointWithDestinationCheck {
|
||||
var e endpointWithDestinationCheck
|
||||
e.Endpoint.Init(ethernet.New(ep), &e)
|
||||
return &e
|
||||
}
|
||||
|
||||
// endpointWithDestinationCheck is a link endpoint that checks the destination
|
||||
// link address before delivering network packets to the network dispatcher.
|
||||
type endpointWithDestinationCheck struct {
|
||||
nested.Endpoint
|
||||
}
|
||||
|
||||
// DeliverNetworkPacket implements stack.NetworkDispatcher.
|
||||
func (e *endpointWithDestinationCheck) DeliverNetworkPacket(src, dst tcpip.LinkAddress, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
|
||||
if dst == e.Endpoint.LinkAddress() || dst == header.EthernetBroadcastAddress || header.IsMulticastEthernetAddress(dst) {
|
||||
e.Endpoint.DeliverNetworkPacket(src, dst, proto, pkt)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForwarding(t *testing.T) {
|
||||
const (
|
||||
host1NICID = 1
|
||||
@@ -209,16 +238,16 @@ func TestForwarding(t *testing.T) {
|
||||
host1NIC, routerNIC1 := pipe.New(linkAddr1, linkAddr2)
|
||||
routerNIC2, host2NIC := pipe.New(linkAddr3, linkAddr4)
|
||||
|
||||
if err := host1Stack.CreateNIC(host1NICID, ethernet.New(host1NIC)); err != nil {
|
||||
if err := host1Stack.CreateNIC(host1NICID, newEthernetEndpoint(host1NIC)); err != nil {
|
||||
t.Fatalf("host1Stack.CreateNIC(%d, _): %s", host1NICID, err)
|
||||
}
|
||||
if err := routerStack.CreateNIC(routerNICID1, ethernet.New(routerNIC1)); err != nil {
|
||||
if err := routerStack.CreateNIC(routerNICID1, newEthernetEndpoint(routerNIC1)); err != nil {
|
||||
t.Fatalf("routerStack.CreateNIC(%d, _): %s", routerNICID1, err)
|
||||
}
|
||||
if err := routerStack.CreateNIC(routerNICID2, ethernet.New(routerNIC2)); err != nil {
|
||||
if err := routerStack.CreateNIC(routerNICID2, newEthernetEndpoint(routerNIC2)); err != nil {
|
||||
t.Fatalf("routerStack.CreateNIC(%d, _): %s", routerNICID2, err)
|
||||
}
|
||||
if err := host2Stack.CreateNIC(host2NICID, ethernet.New(host2NIC)); err != nil {
|
||||
if err := host2Stack.CreateNIC(host2NICID, newEthernetEndpoint(host2NIC)); err != nil {
|
||||
t.Fatalf("host2Stack.CreateNIC(%d, _): %s", host2NICID, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/link/pipe"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
||||
@@ -133,10 +132,10 @@ func TestPing(t *testing.T) {
|
||||
|
||||
host1NIC, host2NIC := pipe.New(linkAddr1, linkAddr2)
|
||||
|
||||
if err := host1Stack.CreateNIC(host1NICID, ethernet.New(host1NIC)); err != nil {
|
||||
if err := host1Stack.CreateNIC(host1NICID, newEthernetEndpoint(host1NIC)); err != nil {
|
||||
t.Fatalf("host1Stack.CreateNIC(%d, _): %s", host1NICID, err)
|
||||
}
|
||||
if err := host2Stack.CreateNIC(host2NICID, ethernet.New(host2NIC)); err != nil {
|
||||
if err := host2Stack.CreateNIC(host2NICID, newEthernetEndpoint(host2NIC)); err != nil {
|
||||
t.Fatalf("host2Stack.CreateNIC(%d, _): %s", host2NICID, err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user