wire_linux.go 1.2 KB

1234567891011121314151617181920212223242526272829303132
  1. package wire
  2. import (
  3. "fmt"
  4. "github.com/slackhq/nebula/overlay/tio/virtio"
  5. )
  6. // PerSegment invokes fn once per segment of pkt. For non-GSO pkts
  7. // fn is called once with pkt.Bytes (no segmentation, no copy). For GSO/USO
  8. // superpackets fn is called once per segment with a slice of pkt.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: pkt is
  11. // consumed by this call and its bytes are in an undefined state when
  12. // PerSegment returns. Callers must not retain pkt or any earlier
  13. // seg slice past fn's return for that segment. The scratch parameter is
  14. // unused on the destructive path and kept only for cross-platform
  15. // signature compatibility. Aborts and returns the first error from fn or
  16. // from per-segment construction.
  17. func (t *TunPacket) PerSegment(fn func(seg []byte) error) error {
  18. if !t.Meta.IsSuperpacket() {
  19. return fn(t.Bytes)
  20. }
  21. switch t.Meta.Proto {
  22. case GSOProtoTCP:
  23. return virtio.SegmentTCP(t.Bytes, t.Meta.HdrLen, t.Meta.CsumStart, t.Meta.Size, fn)
  24. case GSOProtoUDP:
  25. return virtio.SegmentUDP(t.Bytes, t.Meta.HdrLen, t.Meta.CsumStart, t.Meta.Size, fn)
  26. default:
  27. return fmt.Errorf("unsupported gso proto: %d", t.Meta.Proto)
  28. }
  29. }