outpacket.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package packet
  2. import (
  3. "github.com/slackhq/nebula/util/virtio"
  4. "golang.org/x/sys/unix"
  5. )
  6. type OutPacket struct {
  7. Segments [][]byte
  8. // SegmentHeaders maps to the first virtio.NetHdrSize+14 bytes of Segments[n]
  9. SegmentHeaders [][]byte
  10. // SegmentPayloads maps to the remaining bytes of Segments[n]
  11. SegmentPayloads [][]byte
  12. // SegmentIDs is the list of underlying buffer IDs of Segments.
  13. // SegmentIDs, Segments, SegmentHeaders, SegmentPayloads should all have the same length at all times!
  14. SegmentIDs []uint16
  15. }
  16. func NewOut() *OutPacket {
  17. out := new(OutPacket)
  18. out.Segments = make([][]byte, 0, 64)
  19. out.SegmentHeaders = make([][]byte, 0, 64)
  20. out.SegmentPayloads = make([][]byte, 0, 64)
  21. out.SegmentIDs = make([]uint16, 0, 64)
  22. return out
  23. }
  24. func (pkt *OutPacket) Reset() {
  25. pkt.Segments = pkt.Segments[:0]
  26. pkt.SegmentPayloads = pkt.SegmentPayloads[:0]
  27. pkt.SegmentHeaders = pkt.SegmentHeaders[:0]
  28. pkt.SegmentIDs = pkt.SegmentIDs[:0]
  29. }
  30. // DestroyLastSegment removes the contents of the last segment in the list.
  31. // Use this to handle firewall drops or similar, but still hand the segment buffer back to the underlying driver.
  32. // Implementations shall discard zero-length segments internally.
  33. func (pkt *OutPacket) DestroyLastSegment() {
  34. if len(pkt.Segments) == 0 {
  35. return
  36. }
  37. lastSeg := len(pkt.SegmentIDs) - 1
  38. pkt.SegmentPayloads[lastSeg] = pkt.SegmentPayloads[lastSeg][:0]
  39. pkt.SegmentHeaders[lastSeg] = pkt.SegmentHeaders[lastSeg][:0]
  40. pkt.Segments[lastSeg] = pkt.Segments[lastSeg][:0]
  41. }
  42. func (pkt *OutPacket) UseSegment(segID uint16, seg []byte, isV6 bool) int {
  43. pkt.SegmentIDs = append(pkt.SegmentIDs, segID)
  44. pkt.Segments = append(pkt.Segments, seg) //todo do we need this?
  45. vhdr := virtio.NetHdr{ //todo
  46. Flags: unix.VIRTIO_NET_HDR_F_DATA_VALID,
  47. GSOType: unix.VIRTIO_NET_HDR_GSO_NONE,
  48. HdrLen: 0,
  49. GSOSize: 0,
  50. CsumStart: 0,
  51. CsumOffset: 0,
  52. NumBuffers: 0,
  53. }
  54. hdr := seg[0 : virtio.NetHdrSize+14]
  55. _ = vhdr.Encode(hdr)
  56. if isV6 {
  57. hdr[virtio.NetHdrSize+14-2] = 0x86
  58. hdr[virtio.NetHdrSize+14-1] = 0xdd
  59. } else {
  60. hdr[virtio.NetHdrSize+14-2] = 0x08
  61. hdr[virtio.NetHdrSize+14-1] = 0x00
  62. }
  63. pkt.SegmentHeaders = append(pkt.SegmentHeaders, hdr)
  64. pkt.SegmentPayloads = append(pkt.SegmentPayloads, seg[virtio.NetHdrSize+14:])
  65. return len(pkt.SegmentIDs) - 1
  66. }