Skip to content

Commit

Permalink
slayers: recycle path when decoding
Browse files Browse the repository at this point in the history
In `slayers.SCION.DecodeFromBytes`, we allocate a new path for the
correct path type on every invocation. This negates the advantages of
recycling the layer object.

Introduce a "recycling bin" for paths that can be reused in the SCION
layer's DecodeFromBytes.
This is only used when explicitly enabled, as it only makes sense if the
layer is really reused for parsing. This opt-in also avoids issues with
tests that deep-compare the SCION layer with an expected value where
this recycling bin is empty..

Closes #4147

GitOrigin-RevId: cd7c81e4e062822bcc948eae4363c9544721f4d0
  • Loading branch information
matzf authored and oncilla committed Mar 12, 2022
1 parent 4e0872f commit dd97571
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
5 changes: 5 additions & 0 deletions go/lib/slayers/path/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ func NewPath(pathType Type) (Path, error) {
return pm.New(), nil
}

// NewRawPath returns a new raw path that can hold any path type.
func NewRawPath() Path {
return &rawPath{}
}

type rawPath struct {
raw []byte
pathType Type
Expand Down
33 changes: 32 additions & 1 deletion go/lib/slayers/scion.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ type SCION struct {

// Path is the path contained in the SCION header. It depends on the PathType field.
Path path.Path

pathPool []path.Path
pathPoolRaw path.Path
}

func (s *SCION) LayerType() gopacket.LayerType {
Expand Down Expand Up @@ -244,7 +247,7 @@ func (s *SCION) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
return serrors.New("provided buffer is too small", "expected", minLen, "actual", len(data))
}

s.Path, err = path.NewPath(s.PathType)
s.Path, err = s.getPath(s.PathType)
if err != nil {
return err
}
Expand All @@ -259,6 +262,34 @@ func (s *SCION) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
return nil
}

// RecyclePaths enables recycling of paths used for DecodeFromBytes. This is
// only useful if the layer itself is reused.
// When this is enabled, the Path instance may be overwritten in
// DecodeFromBytes. No references to Path should be kept in use between
// invocations of DecodeFromBytes.
func (s *SCION) RecyclePaths() {
if s.pathPool == nil {
s.pathPool = []path.Path{
empty.PathType: empty.Path{},
onehop.PathType: &onehop.Path{},
scion.PathType: &scion.Raw{},
epic.PathType: &epic.Path{},
}
s.pathPoolRaw = path.NewRawPath()
}
}

// getPath returns a new or recycled path for pathType
func (s *SCION) getPath(pathType path.Type) (path.Path, error) {
if s.pathPool == nil {
return path.NewPath(pathType)
}
if int(pathType) < len(s.pathPool) {
return s.pathPool[pathType], nil
}
return s.pathPoolRaw, nil
}

func decodeSCION(data []byte, pb gopacket.PacketBuilder) error {
scn := &SCION{}
err := scn.DecodeFromBytes(data, pb)
Expand Down
4 changes: 3 additions & 1 deletion go/pkg/router/dataplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ type processResult struct {
}

func newPacketProcessor(d *DataPlane, ingressID uint16) *scionPacketProcessor {
return &scionPacketProcessor{
p := &scionPacketProcessor{
d: d,
ingressID: ingressID,
buffer: gopacket.NewSerializeBuffer(),
Expand All @@ -563,6 +563,8 @@ func newPacketProcessor(d *DataPlane, ingressID uint16) *scionPacketProcessor {
epicInput: make([]byte, libepic.MACBufferSize),
},
}
p.scionLayer.RecyclePaths()
return p
}

func (p *scionPacketProcessor) reset() error {
Expand Down

0 comments on commit dd97571

Please sign in to comment.