tun_linux_offload.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. //go:build linux && !android
  2. // +build linux,!android
  3. package tio
  4. import (
  5. "fmt"
  6. "golang.org/x/sys/unix"
  7. "github.com/slackhq/nebula/overlay/tio/virtio"
  8. )
  9. // protoFromGSOType maps a virtio_net_hdr gsoType to the GSOProto value the
  10. // segment-time helpers use. Returns an error for GSO_NONE or any unknown
  11. // value. The caller should only invoke this on a confirmed superpacket.
  12. func protoFromGSOType(t uint8) (GSOProto, error) {
  13. switch t &^ unix.VIRTIO_NET_HDR_GSO_ECN {
  14. case unix.VIRTIO_NET_HDR_GSO_TCPV4, unix.VIRTIO_NET_HDR_GSO_TCPV6:
  15. return GSOProtoTCP, nil
  16. case unix.VIRTIO_NET_HDR_GSO_UDP_L4:
  17. return GSOProtoUDP, nil
  18. default:
  19. return 0, fmt.Errorf("unsupported virtio gso type: %d", t)
  20. }
  21. }
  22. // gsoTypeFromProto is the reverse of protoFromGSOType
  23. func gsoTypeFromProto(proto GSOProto, ipVer uint8) uint8 {
  24. switch {
  25. case proto == GSOProtoUDP && (ipVer == 4 || ipVer == 6):
  26. return unix.VIRTIO_NET_HDR_GSO_UDP_L4
  27. case ipVer == 6:
  28. return unix.VIRTIO_NET_HDR_GSO_TCPV6
  29. case ipVer == 4:
  30. return unix.VIRTIO_NET_HDR_GSO_TCPV4
  31. default:
  32. return unix.VIRTIO_NET_HDR_GSO_NONE
  33. }
  34. }
  35. // SegmentSuperpacket invokes fn once per segment of pkt.
  36. // For non-GSO pkts fn is called once with pkt.Bytes.
  37. // For GSO/USO superpackets, fn is called once per segment with a slice of pkt.Bytes holding that segment's plaintext
  38. // (a freshly-patched L3+L4 header sliced in front of the original payload chunk).
  39. // This slicing is destructive: pkt is consumed by this call.
  40. // Aborts and returns the first error from fn or from per-segment construction.
  41. func SegmentSuperpacket(pkt Packet, fn func(seg []byte) error) error {
  42. if !pkt.GSO.IsSuperpacket() {
  43. return fn(pkt.Bytes)
  44. }
  45. switch pkt.GSO.Proto {
  46. case GSOProtoTCP:
  47. return virtio.SegmentTCP(pkt.Bytes, pkt.GSO.HdrLen, pkt.GSO.CsumStart, pkt.GSO.Size, fn)
  48. case GSOProtoUDP:
  49. return virtio.SegmentUDP(pkt.Bytes, pkt.GSO.HdrLen, pkt.GSO.CsumStart, pkt.GSO.Size, fn)
  50. default:
  51. return fmt.Errorf("unsupported gso proto: %d", pkt.GSO.Proto)
  52. }
  53. }