syscall.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. package internal
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "runtime"
  6. "unsafe"
  7. "github.com/cilium/ebpf/internal/unix"
  8. )
  9. //go:generate stringer -output syscall_string.go -type=BPFCmd
  10. // BPFCmd identifies a subcommand of the bpf syscall.
  11. type BPFCmd int
  12. // Well known BPF commands.
  13. const (
  14. BPF_MAP_CREATE BPFCmd = iota
  15. BPF_MAP_LOOKUP_ELEM
  16. BPF_MAP_UPDATE_ELEM
  17. BPF_MAP_DELETE_ELEM
  18. BPF_MAP_GET_NEXT_KEY
  19. BPF_PROG_LOAD
  20. BPF_OBJ_PIN
  21. BPF_OBJ_GET
  22. BPF_PROG_ATTACH
  23. BPF_PROG_DETACH
  24. BPF_PROG_TEST_RUN
  25. BPF_PROG_GET_NEXT_ID
  26. BPF_MAP_GET_NEXT_ID
  27. BPF_PROG_GET_FD_BY_ID
  28. BPF_MAP_GET_FD_BY_ID
  29. BPF_OBJ_GET_INFO_BY_FD
  30. BPF_PROG_QUERY
  31. BPF_RAW_TRACEPOINT_OPEN
  32. BPF_BTF_LOAD
  33. BPF_BTF_GET_FD_BY_ID
  34. BPF_TASK_FD_QUERY
  35. BPF_MAP_LOOKUP_AND_DELETE_ELEM
  36. BPF_MAP_FREEZE
  37. BPF_BTF_GET_NEXT_ID
  38. BPF_MAP_LOOKUP_BATCH
  39. BPF_MAP_LOOKUP_AND_DELETE_BATCH
  40. BPF_MAP_UPDATE_BATCH
  41. BPF_MAP_DELETE_BATCH
  42. BPF_LINK_CREATE
  43. BPF_LINK_UPDATE
  44. BPF_LINK_GET_FD_BY_ID
  45. BPF_LINK_GET_NEXT_ID
  46. BPF_ENABLE_STATS
  47. BPF_ITER_CREATE
  48. )
  49. // BPF wraps SYS_BPF.
  50. //
  51. // Any pointers contained in attr must use the Pointer type from this package.
  52. func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
  53. r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
  54. runtime.KeepAlive(attr)
  55. var err error
  56. if errNo != 0 {
  57. err = errNo
  58. }
  59. return r1, err
  60. }
  61. type BPFProgAttachAttr struct {
  62. TargetFd uint32
  63. AttachBpfFd uint32
  64. AttachType uint32
  65. AttachFlags uint32
  66. ReplaceBpfFd uint32
  67. }
  68. func BPFProgAttach(attr *BPFProgAttachAttr) error {
  69. _, err := BPF(BPF_PROG_ATTACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  70. return err
  71. }
  72. type BPFProgDetachAttr struct {
  73. TargetFd uint32
  74. AttachBpfFd uint32
  75. AttachType uint32
  76. }
  77. func BPFProgDetach(attr *BPFProgDetachAttr) error {
  78. _, err := BPF(BPF_PROG_DETACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  79. return err
  80. }
  81. type BPFEnableStatsAttr struct {
  82. StatsType uint32
  83. }
  84. func BPFEnableStats(attr *BPFEnableStatsAttr) (*FD, error) {
  85. ptr, err := BPF(BPF_ENABLE_STATS, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
  86. if err != nil {
  87. return nil, fmt.Errorf("enable stats: %w", err)
  88. }
  89. return NewFD(uint32(ptr)), nil
  90. }
  91. type bpfObjAttr struct {
  92. fileName Pointer
  93. fd uint32
  94. fileFlags uint32
  95. }
  96. const bpfFSType = 0xcafe4a11
  97. // BPFObjPin wraps BPF_OBJ_PIN.
  98. func BPFObjPin(fileName string, fd *FD) error {
  99. dirName := filepath.Dir(fileName)
  100. var statfs unix.Statfs_t
  101. if err := unix.Statfs(dirName, &statfs); err != nil {
  102. return err
  103. }
  104. if uint64(statfs.Type) != bpfFSType {
  105. return fmt.Errorf("%s is not on a bpf filesystem", fileName)
  106. }
  107. value, err := fd.Value()
  108. if err != nil {
  109. return err
  110. }
  111. attr := bpfObjAttr{
  112. fileName: NewStringPointer(fileName),
  113. fd: value,
  114. }
  115. _, err = BPF(BPF_OBJ_PIN, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  116. if err != nil {
  117. return fmt.Errorf("pin object %s: %w", fileName, err)
  118. }
  119. return nil
  120. }
  121. // BPFObjGet wraps BPF_OBJ_GET.
  122. func BPFObjGet(fileName string) (*FD, error) {
  123. attr := bpfObjAttr{
  124. fileName: NewStringPointer(fileName),
  125. }
  126. ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  127. if err != nil {
  128. return nil, fmt.Errorf("get object %s: %w", fileName, err)
  129. }
  130. return NewFD(uint32(ptr)), nil
  131. }
  132. type bpfObjGetInfoByFDAttr struct {
  133. fd uint32
  134. infoLen uint32
  135. info Pointer
  136. }
  137. // BPFObjGetInfoByFD wraps BPF_OBJ_GET_INFO_BY_FD.
  138. //
  139. // Available from 4.13.
  140. func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
  141. value, err := fd.Value()
  142. if err != nil {
  143. return err
  144. }
  145. attr := bpfObjGetInfoByFDAttr{
  146. fd: value,
  147. infoLen: uint32(size),
  148. info: NewPointer(info),
  149. }
  150. _, err = BPF(BPF_OBJ_GET_INFO_BY_FD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
  151. if err != nil {
  152. return fmt.Errorf("fd %v: %w", fd, err)
  153. }
  154. return nil
  155. }