header_linux.go 2.0 KB

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