header_linux.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //go:build linux && !android
  2. // +build linux,!android
  3. package virtio
  4. import (
  5. "encoding/binary"
  6. "golang.org/x/sys/unix"
  7. )
  8. // Size is the on-wire length of struct virtio_net_hdr the kernel
  9. // prepends/expects on a TUN opened with IFF_VNET_HDR (TUNSETVNETHDRSZ
  10. // not set).
  11. const Size = 10
  12. // Hdr is the Go view of the legacy virtio_net_hdr.
  13. type Hdr struct {
  14. Flags uint8
  15. gsoType uint8 //private to avoid mistakes wrt the 0x80 VIRTIO_NET_HDR_GSO_ECN flag, ORed with the other "GSO types"
  16. HdrLen uint16
  17. GSOSize uint16
  18. CsumStart uint16
  19. CsumOffset uint16
  20. }
  21. func NewHeader(flags, gsoType uint8, hdrLen, gsoSize, csumStart, csumOffset uint16) Hdr {
  22. return Hdr{
  23. Flags: flags,
  24. gsoType: gsoType,
  25. HdrLen: hdrLen,
  26. GSOSize: gsoSize,
  27. CsumStart: csumStart,
  28. CsumOffset: csumOffset,
  29. }
  30. }
  31. // Decode reads a virtio_net_hdr in host byte order (TUN default; we never
  32. // call TUNSETVNETLE so the kernel matches our endianness).
  33. func (h *Hdr) Decode(b []byte) {
  34. h.Flags = b[0]
  35. h.gsoType = b[1]
  36. h.HdrLen = binary.NativeEndian.Uint16(b[2:4])
  37. h.GSOSize = binary.NativeEndian.Uint16(b[4:6])
  38. h.CsumStart = binary.NativeEndian.Uint16(b[6:8])
  39. h.CsumOffset = binary.NativeEndian.Uint16(b[8:10])
  40. }
  41. func EncodeHeader(b []byte, flags, gsoType uint8, hdrLen, gsoSize, csumStart, csumOffset uint16) {
  42. b[0] = flags
  43. b[1] = gsoType
  44. binary.NativeEndian.PutUint16(b[2:4], hdrLen)
  45. binary.NativeEndian.PutUint16(b[4:6], gsoSize)
  46. binary.NativeEndian.PutUint16(b[6:8], csumStart)
  47. binary.NativeEndian.PutUint16(b[8:10], csumOffset)
  48. }
  49. // Encode is the inverse of Decode: writes the virtio_net_hdr fields into b
  50. // (must be at least Size bytes). Used to emit a TSO superpacket on egress.
  51. func (h *Hdr) Encode(b []byte) {
  52. EncodeHeader(b, h.Flags, h.gsoType, h.HdrLen, h.GSOSize, h.CsumStart, h.CsumOffset)
  53. }
  54. // GSOType returns gsoType with the ECN-flag masked out
  55. func (h *Hdr) GSOType() uint8 {
  56. return h.gsoType &^ unix.VIRTIO_NET_HDR_GSO_ECN
  57. }
  58. func (h *Hdr) HasECNFlag() bool {
  59. return h.gsoType&unix.VIRTIO_NET_HDR_GSO_ECN != 0
  60. }
  61. func (h *Hdr) SetGSOType(x uint8) {
  62. h.gsoType = x
  63. }