wire_linux.go 1.1 KB

123456789101112131415161718192021222324252627282930
  1. package wire
  2. import (
  3. "fmt"
  4. "github.com/slackhq/nebula/overlay/tio/virtio"
  5. )
  6. // PerSegment invokes fn once per segment of t. For non-GSO packets fn is
  7. // called once with t.Bytes (no segmentation, no copy). For GSO/USO
  8. // superpackets fn is called once per segment with a slice of t.Bytes
  9. // holding that segment's plaintext (a freshly-patched L3+L4 header sliced
  10. // in front of the original payload chunk). The slide is destructive: t is
  11. // consumed by this call and its bytes are in an undefined state when
  12. // PerSegment returns. Callers must not retain t or any earlier seg slice
  13. // past fn's return for that segment. Aborts and returns the first error
  14. // from fn or from per-segment construction.
  15. func (t *TunPacket) PerSegment(fn func(seg []byte) error) error {
  16. if !t.Meta.IsSuperpacket() {
  17. return fn(t.Bytes)
  18. }
  19. switch t.Meta.Proto {
  20. case GSOProtoTCP:
  21. return virtio.SegmentTCP(t.Bytes, t.Meta.HdrLen, t.Meta.CsumStart, t.Meta.Size, fn)
  22. case GSOProtoUDP:
  23. return virtio.SegmentUDP(t.Bytes, t.Meta.HdrLen, t.Meta.CsumStart, t.Meta.Size, fn)
  24. default:
  25. return fmt.Errorf("unsupported gso proto: %d", t.Meta.Proto)
  26. }
  27. }