tun_linux_offload.go 1.9 KB

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