Skip to content

Commit

Permalink
modified test cases and PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
rohrerj committed Sep 8, 2023
1 parent 650a640 commit edc8523
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 143 deletions.
40 changes: 20 additions & 20 deletions router/dataplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,26 +116,26 @@ type DataPlane struct {
}

var (
alreadySet = serrors.New("already set")
invalidSrcIA = serrors.New("invalid source ISD-AS")
invalidDstIA = serrors.New("invalid destination ISD-AS")
invalidSrcAddrForTransit = serrors.New("invalid source address for transit pkt")
cannotRoute = serrors.New("cannot route, dropping pkt")
emptyValue = serrors.New("empty value")
malformedPath = serrors.New("malformed path content")
modifyExisting = serrors.New("modifying a running dataplane is not allowed")
noSVCBackend = serrors.New("cannot find internal IP for the SVC")
unsupportedPathType = serrors.New("unsupported path type")
unsupportedPathTypeNextHeader = serrors.New("unsupported combination")
noBFDSessionFound = serrors.New("no BFD sessions was found")
noBFDSessionConfigured = serrors.New("no BFD sessions have been configured")
errBFDDisabled = serrors.New("BFD is disabled")
bfdSessionDown = serrors.New("bfd session down")
expiredHop = serrors.New("expired hop")
ingressInterfaceInvalid = serrors.New("ingress interface invalid")
macVerificationFailed = serrors.New("MAC verification failed")
badPacketSize = serrors.New("bad packet size")
slowPathRequired = serrors.New("slow-path required")
alreadySet = errors.New("already set")
invalidSrcIA = errors.New("invalid source ISD-AS")
invalidDstIA = errors.New("invalid destination ISD-AS")
invalidSrcAddrForTransit = errors.New("invalid source address for transit pkt")
cannotRoute = errors.New("cannot route, dropping pkt")
emptyValue = errors.New("empty value")
malformedPath = errors.New("malformed path content")
modifyExisting = errors.New("modifying a running dataplane is not allowed")
noSVCBackend = errors.New("cannot find internal IP for the SVC")
unsupportedPathType = errors.New("unsupported path type")
unsupportedPathTypeNextHeader = errors.New("unsupported combination")
noBFDSessionFound = errors.New("no BFD sessions was found")
noBFDSessionConfigured = errors.New("no BFD sessions have been configured")
errBFDDisabled = errors.New("BFD is disabled")
bfdSessionDown = errors.New("bfd session down")
expiredHop = errors.New("expired hop")
ingressInterfaceInvalid = errors.New("ingress interface invalid")
macVerificationFailed = errors.New("MAC verification failed")
badPacketSize = errors.New("bad packet size")
slowPathRequired = errors.New("slow-path required")
// zeroBuffer will be used to reset the Authenticator option in the
// scionPacketProcessor.OptAuth
zeroBuffer = make([]byte, 16)
Expand Down
147 changes: 146 additions & 1 deletion router/dataplane_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ import (
"github.com/google/gopacket"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/net/ipv4"

"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/private/serrors"
"github.com/scionproto/scion/pkg/private/util"
"github.com/scionproto/scion/pkg/private/xtest"
"github.com/scionproto/scion/pkg/scrypto"
"github.com/scionproto/scion/pkg/slayers"
"github.com/scionproto/scion/pkg/slayers/path"
"github.com/scionproto/scion/pkg/slayers/path/scion"
underlayconn "github.com/scionproto/scion/private/underlay/conn"
"github.com/scionproto/scion/router/mock_router"
)

var key = []byte("testkey_xxxxxxxx")

// TestReceiver sets up a mocked batchConn, starts the receiver that reads from
// this batchConn and forwards it to the processing routines channels. We verify
// by directly reading from the processing routine channels that we received
Expand Down Expand Up @@ -414,6 +418,146 @@ func TestComputeProcIdErrorCases(t *testing.T) {
}
}

func TestSlowPathProcessing(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
key := []byte("testkey_xxxxxxxx")
payload := []byte("actualpayloadbytes")
testCases := map[string]struct {
mockMsg func() *ipv4.Message
prepareDP func(*gomock.Controller) *DataPlane
expectedSlowPathRequest slowPathRequest
srcInterface uint16
expectedLayerType gopacket.LayerType
}{
"svc nobackend": {
prepareDP: func(ctrl *gomock.Controller) *DataPlane {
return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt := prepBaseMsg(t, payload, 0)
_ = spkt.SetDstAddr(addr.MustParseHost("CS"))
spkt.DstIA = xtest.MustParseIA("1-ff00:0:110")
ret := toMsg(t, spkt, spkt.Path)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: slowPathRequest{
typ: slowPathSCMP,
scmpType: slayers.SCMPTypeDestinationUnreachable,
code: slayers.SCMPCodeNoRoute,
cause: noSVCBackend,
},
expectedLayerType: slayers.LayerTypeSCMPDestinationUnreachable,
},
"svc invalid": {
prepareDP: func(ctrl *gomock.Controller) *DataPlane {
return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt := prepBaseMsg(t, payload, 0)
_ = spkt.SetDstAddr(addr.MustParseHost("CS"))
spkt.DstIA = xtest.MustParseIA("1-ff00:0:110")
ret := toMsg(t, spkt, spkt.Path)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: slowPathRequest{
typ: slowPathSCMP,
scmpType: slayers.SCMPTypeDestinationUnreachable,
code: slayers.SCMPCodeNoRoute,
cause: noSVCBackend,
},
expectedLayerType: slayers.LayerTypeSCMPDestinationUnreachable,
},
"invalid dest": {
prepareDP: func(ctrl *gomock.Controller) *DataPlane {
return NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt := prepBaseMsg(t, payload, 0)
spkt.DstIA = xtest.MustParseIA("1-ff00:0:f1")
ret := toMsg(t, spkt, spkt.Path)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: slowPathRequest{
typ: slowPathSCMP,
scmpType: slayers.SCMPTypeParameterProblem,
code: slayers.SCMPCodeInvalidDestinationAddress,
cause: invalidDstIA,
},
expectedLayerType: slayers.LayerTypeSCMPParameterProblem,
},
}
for name, tc := range testCases {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
dp := tc.prepareDP(ctrl)
input := tc.mockMsg()
result, err := dp.ProcessPkt(tc.srcInterface, input)
assert.ErrorIs(t, err, SlowPathRequired)
selectedResult := slowPathRequest{
typ: result.SlowPathRequest.typ,
scmpType: result.SlowPathRequest.scmpType,
code: result.SlowPathRequest.code,
cause: result.SlowPathRequest.cause,
}
assert.Equal(t, tc.expectedSlowPathRequest, selectedResult)
result, err = dp.ProcessSlowPath(tc.srcInterface, input, result.SlowPathRequest)
assert.NoError(t, err)

// here we parse the result.OutPkt to verify that it contains the correct SCMP
// header and typecodes.
packet := gopacket.NewPacket(result.OutPkt, slayers.LayerTypeSCION, gopacket.Default)
scmpLayer := packet.Layer(slayers.LayerTypeSCMP)
scmp := scmpLayer.(*slayers.SCMP)
expectedTypeCode := slayers.CreateSCMPTypeCode(tc.expectedSlowPathRequest.scmpType,
tc.expectedSlowPathRequest.code)
assert.Equal(t, expectedTypeCode, scmp.TypeCode)
layerFound := false
for _, l := range packet.Layers() {
if l.LayerType() == tc.expectedLayerType {
layerFound = true
break
}
}
assert.True(t, layerFound)
})
}
}

func toMsg(t *testing.T, spkt *slayers.SCION, dpath path.Path) *ipv4.Message {
t.Helper()
ret := &ipv4.Message{}
spkt.Path = dpath
buffer := gopacket.NewSerializeBuffer()
payload := []byte("actualpayloadbytes")
err := gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{FixLengths: true},
spkt, gopacket.Payload(payload))
require.NoError(t, err)
raw := buffer.Bytes()
ret.Buffers = make([][]byte, 1)
ret.Buffers[0] = make([]byte, 1500)
copy(ret.Buffers[0], raw)
ret.N = len(raw)
ret.Buffers[0] = ret.Buffers[0][:ret.N]
return ret
}

func computeMAC(t *testing.T, key []byte, info path.InfoField, hf path.HopField) [path.MacLen]byte {
mac, err := scrypto.InitMac(key)
require.NoError(t, err)
return path.MAC(mac, info, hf, nil)
}

func serializedBaseMsg(t *testing.T, payload []byte, flowId uint32) []byte {
s := prepBaseMsg(t, payload, flowId)
buffer := gopacket.NewSerializeBuffer()
Expand All @@ -440,7 +584,7 @@ func prepBaseMsg(t *testing.T, payload []byte, flowId uint32) *slayers.SCION {
dpath := &scion.Decoded{
Base: scion.Base{
PathMeta: scion.MetaHdr{
CurrHF: 1,
CurrHF: 2,
SegLen: [3]uint8{3, 0, 0},
},
NumINF: 1,
Expand All @@ -456,6 +600,7 @@ func prepBaseMsg(t *testing.T, payload []byte, flowId uint32) *slayers.SCION {
{ConsIngress: 1, ConsEgress: 0},
},
}
dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2])
spkt.Path = dpath
return spkt
}
107 changes: 0 additions & 107 deletions router/dataplane_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,113 +566,6 @@ func TestDataPlaneRun(t *testing.T) {
}
}

func TestSlowPathProcessing(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
key := []byte("testkey_xxxxxxxx")
now := time.Now()
testCases := map[string]struct {
mockMsg func() *ipv4.Message
prepareDP func(*gomock.Controller) *router.DataPlane
expectedSlowPathRequest router.SlowPathRequest
srcInterface uint16
}{
"svc nobackend": {
prepareDP: func(ctrl *gomock.Controller) *router.DataPlane {
return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt, dpath := prepBaseMsg(now)
_ = spkt.SetDstAddr(addr.MustParseHost("CS"))
spkt.DstIA = xtest.MustParseIA("1-ff00:0:110")
dpath.HopFields = []path.HopField{
{ConsIngress: 41, ConsEgress: 40},
{ConsIngress: 31, ConsEgress: 30},
{ConsIngress: 1, ConsEgress: 0},
}
dpath.Base.PathMeta.CurrHF = 2
dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2])
ret := toMsg(t, spkt, dpath)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: router.SlowPathRequest{
Typ: 0,
ScmpType: slayers.SCMPTypeDestinationUnreachable,
Code: slayers.SCMPCodeNoRoute,
},
},
"svc invalid": {
prepareDP: func(ctrl *gomock.Controller) *router.DataPlane {
return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt, dpath := prepBaseMsg(now)
_ = spkt.SetDstAddr(addr.MustParseHost("CS"))
spkt.DstIA = xtest.MustParseIA("1-ff00:0:110")
dpath.HopFields = []path.HopField{
{ConsIngress: 41, ConsEgress: 40},
{ConsIngress: 31, ConsEgress: 30},
{ConsIngress: 1, ConsEgress: 0},
}
dpath.Base.PathMeta.CurrHF = 2
dpath.HopFields[2].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[2])
ret := toMsg(t, spkt, dpath)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: router.SlowPathRequest{
Typ: 0,
ScmpType: slayers.SCMPTypeDestinationUnreachable,
Code: slayers.SCMPCodeNoRoute,
},
},
"invalid dest": {
prepareDP: func(ctrl *gomock.Controller) *router.DataPlane {
return router.NewDP(nil, nil, mock_router.NewMockBatchConn(ctrl), nil,
map[addr.SVC][]*net.UDPAddr{},
xtest.MustParseIA("1-ff00:0:110"), nil, key)
},
mockMsg: func() *ipv4.Message {
spkt, dpath := prepBaseMsg(now)
spkt.DstIA = xtest.MustParseIA("1-ff00:0:f1")
dpath.HopFields = []path.HopField{
{ConsIngress: 41, ConsEgress: 40},
{ConsIngress: 31, ConsEgress: 404},
{ConsIngress: 1, ConsEgress: 0},
}
dpath.Base.PathMeta.CurrHF = 2
dpath.HopFields[1].Mac = computeMAC(t, key, dpath.InfoFields[0], dpath.HopFields[1])
ret := toMsg(t, spkt, dpath)
return ret
},
srcInterface: 1,
expectedSlowPathRequest: router.SlowPathRequest{
Typ: 0,
ScmpType: slayers.SCMPTypeParameterProblem,
Code: slayers.SCMPCodeInvalidDestinationAddress,
},
},
}
for name, tc := range testCases {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
dp := tc.prepareDP(ctrl)
input := tc.mockMsg()
result, err := dp.ProcessPkt(tc.srcInterface, input)
assert.ErrorIs(t, err, router.SlowPathRequired)
assert.Equal(t, tc.expectedSlowPathRequest, result.SlowPathRequest.Wrap())
result, err = dp.ProcessSlowPath(tc.srcInterface, input, result.SlowPathRequest)
assert.NoError(t, err)
})
}
}

func TestProcessPkt(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Expand Down
15 changes: 0 additions & 15 deletions router/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"golang.org/x/net/ipv4"

"github.com/scionproto/scion/pkg/addr"
"github.com/scionproto/scion/pkg/slayers"
"github.com/scionproto/scion/private/topology"
)

Expand Down Expand Up @@ -102,20 +101,6 @@ func (d *DataPlane) ProcessSlowPath(ifID uint16, m *ipv4.Message,
return ProcessResult{processResult: result}, err
}

type SlowPathRequest struct {
Typ int
ScmpType slayers.SCMPType
Code slayers.SCMPCode
}

func (s slowPathRequest) Wrap() SlowPathRequest {
return SlowPathRequest{
Typ: int(s.typ),
ScmpType: s.scmpType,
Code: s.code,
}
}

func ExtractServices(s *services) map[addr.SVC][]*net.UDPAddr {
return s.m
}

0 comments on commit edc8523

Please sign in to comment.