map.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. package ebpf
  2. import (
  3. "fmt"
  4. "unsafe"
  5. "github.com/cilium/ebpf/internal"
  6. "github.com/cilium/ebpf/internal/unix"
  7. "github.com/pkg/errors"
  8. )
  9. // MapSpec defines a Map.
  10. type MapSpec struct {
  11. // Name is passed to the kernel as a debug aid. Must only contain
  12. // alpha numeric and '_' characters.
  13. Name string
  14. Type MapType
  15. KeySize uint32
  16. ValueSize uint32
  17. MaxEntries uint32
  18. Flags uint32
  19. // InnerMap is used as a template for ArrayOfMaps and HashOfMaps
  20. InnerMap *MapSpec
  21. }
  22. func (ms *MapSpec) String() string {
  23. return fmt.Sprintf("%s(keySize=%d, valueSize=%d, maxEntries=%d, flags=%d)", ms.Type, ms.KeySize, ms.ValueSize, ms.MaxEntries, ms.Flags)
  24. }
  25. // Copy returns a copy of the spec.
  26. func (ms *MapSpec) Copy() *MapSpec {
  27. if ms == nil {
  28. return nil
  29. }
  30. cpy := *ms
  31. cpy.InnerMap = ms.InnerMap.Copy()
  32. return &cpy
  33. }
  34. // Map represents a Map file descriptor.
  35. //
  36. // It is not safe to close a map which is used by other goroutines.
  37. //
  38. // Methods which take interface{} arguments by default encode
  39. // them using binary.Read/Write in the machine's native endianness.
  40. //
  41. // Implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
  42. // if you require custom encoding.
  43. type Map struct {
  44. fd *bpfFD
  45. abi MapABI
  46. // Per CPU maps return values larger than the size in the spec
  47. fullValueSize int
  48. }
  49. // NewMapFromFD creates a map from a raw fd.
  50. //
  51. // You should not use fd after calling this function.
  52. func NewMapFromFD(fd int) (*Map, error) {
  53. if fd < 0 {
  54. return nil, errors.New("invalid fd")
  55. }
  56. bpfFd := newBPFFD(uint32(fd))
  57. abi, err := newMapABIFromFd(bpfFd)
  58. if err != nil {
  59. bpfFd.forget()
  60. return nil, err
  61. }
  62. return newMap(bpfFd, abi)
  63. }
  64. // NewMap creates a new Map.
  65. //
  66. // Creating a map for the first time will perform feature detection
  67. // by creating small, temporary maps.
  68. func NewMap(spec *MapSpec) (*Map, error) {
  69. if spec.Type != ArrayOfMaps && spec.Type != HashOfMaps {
  70. return createMap(spec, nil)
  71. }
  72. if spec.InnerMap == nil {
  73. return nil, errors.Errorf("%s requires InnerMap", spec.Type)
  74. }
  75. template, err := createMap(spec.InnerMap, nil)
  76. if err != nil {
  77. return nil, err
  78. }
  79. defer template.Close()
  80. return createMap(spec, template.fd)
  81. }
  82. func createMap(spec *MapSpec, inner *bpfFD) (*Map, error) {
  83. spec = spec.Copy()
  84. switch spec.Type {
  85. case ArrayOfMaps:
  86. fallthrough
  87. case HashOfMaps:
  88. if spec.ValueSize != 0 && spec.ValueSize != 4 {
  89. return nil, errors.Errorf("ValueSize must be zero or four for map of map")
  90. }
  91. spec.ValueSize = 4
  92. case PerfEventArray:
  93. if spec.KeySize != 0 {
  94. return nil, errors.Errorf("KeySize must be zero for perf event array")
  95. }
  96. if spec.ValueSize != 0 {
  97. return nil, errors.Errorf("ValueSize must be zero for perf event array")
  98. }
  99. if spec.MaxEntries == 0 {
  100. n, err := internal.OnlineCPUs()
  101. if err != nil {
  102. return nil, errors.Wrap(err, "perf event array")
  103. }
  104. spec.MaxEntries = uint32(n)
  105. }
  106. spec.KeySize = 4
  107. spec.ValueSize = 4
  108. }
  109. attr := bpfMapCreateAttr{
  110. mapType: spec.Type,
  111. keySize: spec.KeySize,
  112. valueSize: spec.ValueSize,
  113. maxEntries: spec.MaxEntries,
  114. flags: spec.Flags,
  115. }
  116. if inner != nil {
  117. var err error
  118. attr.innerMapFd, err = inner.value()
  119. if err != nil {
  120. return nil, errors.Wrap(err, "map create")
  121. }
  122. }
  123. name, err := newBPFObjName(spec.Name)
  124. if err != nil {
  125. return nil, errors.Wrap(err, "map create")
  126. }
  127. if haveObjName.Result() {
  128. attr.mapName = name
  129. }
  130. fd, err := bpfMapCreate(&attr)
  131. if err != nil {
  132. return nil, errors.Wrap(err, "map create")
  133. }
  134. return newMap(fd, newMapABIFromSpec(spec))
  135. }
  136. func newMap(fd *bpfFD, abi *MapABI) (*Map, error) {
  137. m := &Map{
  138. fd,
  139. *abi,
  140. int(abi.ValueSize),
  141. }
  142. if !abi.Type.hasPerCPUValue() {
  143. return m, nil
  144. }
  145. possibleCPUs, err := internal.PossibleCPUs()
  146. if err != nil {
  147. return nil, err
  148. }
  149. m.fullValueSize = align(int(abi.ValueSize), 8) * possibleCPUs
  150. return m, nil
  151. }
  152. func (m *Map) String() string {
  153. return fmt.Sprintf("%s#%d", m.abi.Type, m.fd)
  154. }
  155. // ABI gets the ABI of the Map
  156. func (m *Map) ABI() MapABI {
  157. return m.abi
  158. }
  159. // Lookup retrieves a value from a Map.
  160. //
  161. // Calls Close() on valueOut if it is of type **Map or **Program,
  162. // and *valueOut is not nil.
  163. //
  164. // Returns an error if the key doesn't exist, see IsNotExist.
  165. func (m *Map) Lookup(key, valueOut interface{}) error {
  166. valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
  167. if err := m.lookup(key, valuePtr); err != nil {
  168. return err
  169. }
  170. if valueBytes == nil {
  171. return nil
  172. }
  173. if m.abi.Type.hasPerCPUValue() {
  174. return unmarshalPerCPUValue(valueOut, int(m.abi.ValueSize), valueBytes)
  175. }
  176. switch value := valueOut.(type) {
  177. case **Map:
  178. m, err := unmarshalMap(valueBytes)
  179. if err != nil {
  180. return err
  181. }
  182. (*value).Close()
  183. *value = m
  184. return nil
  185. case *Map:
  186. return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
  187. case Map:
  188. return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
  189. case **Program:
  190. p, err := unmarshalProgram(valueBytes)
  191. if err != nil {
  192. return err
  193. }
  194. (*value).Close()
  195. *value = p
  196. return nil
  197. case *Program:
  198. return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
  199. case Program:
  200. return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
  201. default:
  202. return unmarshalBytes(valueOut, valueBytes)
  203. }
  204. }
  205. // LookupBytes gets a value from Map.
  206. //
  207. // Returns a nil value if a key doesn't exist.
  208. func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
  209. valueBytes := make([]byte, m.fullValueSize)
  210. valuePtr := newPtr(unsafe.Pointer(&valueBytes[0]))
  211. err := m.lookup(key, valuePtr)
  212. if IsNotExist(err) {
  213. return nil, nil
  214. }
  215. return valueBytes, err
  216. }
  217. func (m *Map) lookup(key interface{}, valueOut syscallPtr) error {
  218. keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
  219. if err != nil {
  220. return errors.WithMessage(err, "can't marshal key")
  221. }
  222. err = bpfMapLookupElem(m.fd, keyPtr, valueOut)
  223. return errors.WithMessage(err, "lookup failed")
  224. }
  225. // MapUpdateFlags controls the behaviour of the Map.Update call.
  226. //
  227. // The exact semantics depend on the specific MapType.
  228. type MapUpdateFlags uint64
  229. const (
  230. // UpdateAny creates a new element or update an existing one.
  231. UpdateAny MapUpdateFlags = iota
  232. // UpdateNoExist creates a new element.
  233. UpdateNoExist MapUpdateFlags = 1 << (iota - 1)
  234. // UpdateExist updates an existing element.
  235. UpdateExist
  236. )
  237. // Put replaces or creates a value in map.
  238. //
  239. // It is equivalent to calling Update with UpdateAny.
  240. func (m *Map) Put(key, value interface{}) error {
  241. return m.Update(key, value, UpdateAny)
  242. }
  243. // Update changes the value of a key.
  244. func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
  245. keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
  246. if err != nil {
  247. return errors.WithMessage(err, "can't marshal key")
  248. }
  249. var valuePtr syscallPtr
  250. if m.abi.Type.hasPerCPUValue() {
  251. valuePtr, err = marshalPerCPUValue(value, int(m.abi.ValueSize))
  252. } else {
  253. valuePtr, err = marshalPtr(value, int(m.abi.ValueSize))
  254. }
  255. if err != nil {
  256. return errors.WithMessage(err, "can't marshal value")
  257. }
  258. return bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags))
  259. }
  260. // Delete removes a value.
  261. //
  262. // Returns an error if the key does not exist, see IsNotExist.
  263. func (m *Map) Delete(key interface{}) error {
  264. keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
  265. if err != nil {
  266. return errors.WithMessage(err, "can't marshal key")
  267. }
  268. err = bpfMapDeleteElem(m.fd, keyPtr)
  269. return errors.WithMessage(err, "can't delete key")
  270. }
  271. // NextKey finds the key following an initial key.
  272. //
  273. // See NextKeyBytes for details.
  274. func (m *Map) NextKey(key, nextKeyOut interface{}) error {
  275. nextKeyPtr, nextKeyBytes := makeBuffer(nextKeyOut, int(m.abi.KeySize))
  276. if err := m.nextKey(key, nextKeyPtr); err != nil {
  277. return err
  278. }
  279. if nextKeyBytes == nil {
  280. return nil
  281. }
  282. err := unmarshalBytes(nextKeyOut, nextKeyBytes)
  283. return errors.WithMessage(err, "can't unmarshal next key")
  284. }
  285. // NextKeyBytes returns the key following an initial key as a byte slice.
  286. //
  287. // Passing nil will return the first key.
  288. //
  289. // Use Iterate if you want to traverse all entries in the map.
  290. func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
  291. nextKey := make([]byte, m.abi.KeySize)
  292. nextKeyPtr := newPtr(unsafe.Pointer(&nextKey[0]))
  293. err := m.nextKey(key, nextKeyPtr)
  294. if IsNotExist(err) {
  295. return nil, nil
  296. }
  297. return nextKey, err
  298. }
  299. func (m *Map) nextKey(key interface{}, nextKeyOut syscallPtr) error {
  300. var (
  301. keyPtr syscallPtr
  302. err error
  303. )
  304. if key != nil {
  305. keyPtr, err = marshalPtr(key, int(m.abi.KeySize))
  306. if err != nil {
  307. return errors.WithMessage(err, "can't marshal key")
  308. }
  309. }
  310. err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut)
  311. return errors.WithMessage(err, "can't get next key")
  312. }
  313. // Iterate traverses a map.
  314. //
  315. // It's safe to create multiple iterators at the same time.
  316. //
  317. // It's not possible to guarantee that all keys in a map will be
  318. // returned if there are concurrent modifications to the map.
  319. func (m *Map) Iterate() *MapIterator {
  320. return newMapIterator(m)
  321. }
  322. // Close removes a Map
  323. func (m *Map) Close() error {
  324. if m == nil {
  325. // This makes it easier to clean up when iterating maps
  326. // of maps / programs.
  327. return nil
  328. }
  329. return m.fd.close()
  330. }
  331. // FD gets the file descriptor of the Map.
  332. //
  333. // Calling this function is invalid after Close has been called.
  334. func (m *Map) FD() int {
  335. fd, err := m.fd.value()
  336. if err != nil {
  337. // Best effort: -1 is the number most likely to be an
  338. // invalid file descriptor.
  339. return -1
  340. }
  341. return int(fd)
  342. }
  343. // Clone creates a duplicate of the Map.
  344. //
  345. // Closing the duplicate does not affect the original, and vice versa.
  346. // Changes made to the map are reflected by both instances however.
  347. //
  348. // Cloning a nil Map returns nil.
  349. func (m *Map) Clone() (*Map, error) {
  350. if m == nil {
  351. return nil, nil
  352. }
  353. dup, err := m.fd.dup()
  354. if err != nil {
  355. return nil, errors.Wrap(err, "can't clone map")
  356. }
  357. return newMap(dup, &m.abi)
  358. }
  359. // Pin persists the map past the lifetime of the process that created it.
  360. //
  361. // This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
  362. func (m *Map) Pin(fileName string) error {
  363. return bpfPinObject(fileName, m.fd)
  364. }
  365. // LoadPinnedMap load a Map from a BPF file.
  366. //
  367. // Requires at least Linux 4.13, and is not compatible with
  368. // nested maps. Use LoadPinnedMapExplicit in these situations.
  369. func LoadPinnedMap(fileName string) (*Map, error) {
  370. fd, err := bpfGetObject(fileName)
  371. if err != nil {
  372. return nil, err
  373. }
  374. abi, err := newMapABIFromFd(fd)
  375. if err != nil {
  376. _ = fd.close()
  377. return nil, err
  378. }
  379. return newMap(fd, abi)
  380. }
  381. // LoadPinnedMapExplicit loads a map with explicit parameters.
  382. func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
  383. fd, err := bpfGetObject(fileName)
  384. if err != nil {
  385. return nil, err
  386. }
  387. return newMap(fd, abi)
  388. }
  389. func unmarshalMap(buf []byte) (*Map, error) {
  390. if len(buf) != 4 {
  391. return nil, errors.New("map id requires 4 byte value")
  392. }
  393. // Looking up an entry in a nested map or prog array returns an id,
  394. // not an fd.
  395. id := internal.NativeEndian.Uint32(buf)
  396. fd, err := bpfGetMapFDByID(id)
  397. if err != nil {
  398. return nil, err
  399. }
  400. abi, err := newMapABIFromFd(fd)
  401. if err != nil {
  402. _ = fd.close()
  403. return nil, err
  404. }
  405. return newMap(fd, abi)
  406. }
  407. // MarshalBinary implements BinaryMarshaler.
  408. func (m *Map) MarshalBinary() ([]byte, error) {
  409. fd, err := m.fd.value()
  410. if err != nil {
  411. return nil, err
  412. }
  413. buf := make([]byte, 4)
  414. internal.NativeEndian.PutUint32(buf, fd)
  415. return buf, nil
  416. }
  417. // MapIterator iterates a Map.
  418. //
  419. // See Map.Iterate.
  420. type MapIterator struct {
  421. target *Map
  422. prevKey interface{}
  423. prevBytes []byte
  424. count, maxEntries uint32
  425. done bool
  426. err error
  427. }
  428. func newMapIterator(target *Map) *MapIterator {
  429. return &MapIterator{
  430. target: target,
  431. maxEntries: target.abi.MaxEntries,
  432. prevBytes: make([]byte, int(target.abi.KeySize)),
  433. }
  434. }
  435. var errIterationAborted = errors.New("iteration aborted")
  436. // Next decodes the next key and value.
  437. //
  438. // Iterating a hash map from which keys are being deleted is not
  439. // safe. You may see the same key multiple times. Iteration may
  440. // also abort with an error, see IsIterationAborted.
  441. //
  442. // Returns false if there are no more entries. You must check
  443. // the result of Err afterwards.
  444. //
  445. // See Map.Get for further caveats around valueOut.
  446. func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
  447. if mi.err != nil || mi.done {
  448. return false
  449. }
  450. for ; mi.count < mi.maxEntries; mi.count++ {
  451. var nextBytes []byte
  452. nextBytes, mi.err = mi.target.NextKeyBytes(mi.prevKey)
  453. if mi.err != nil {
  454. return false
  455. }
  456. if nextBytes == nil {
  457. mi.done = true
  458. return false
  459. }
  460. // The user can get access to nextBytes since unmarshalBytes
  461. // does not copy when unmarshaling into a []byte.
  462. // Make a copy to prevent accidental corruption of
  463. // iterator state.
  464. copy(mi.prevBytes, nextBytes)
  465. mi.prevKey = mi.prevBytes
  466. mi.err = mi.target.Lookup(nextBytes, valueOut)
  467. if IsNotExist(mi.err) {
  468. // Even though the key should be valid, we couldn't look up
  469. // its value. If we're iterating a hash map this is probably
  470. // because a concurrent delete removed the value before we
  471. // could get it. This means that the next call to NextKeyBytes
  472. // is very likely to restart iteration.
  473. // If we're iterating one of the fd maps like
  474. // ProgramArray it means that a given slot doesn't have
  475. // a valid fd associated. It's OK to continue to the next slot.
  476. continue
  477. }
  478. if mi.err != nil {
  479. return false
  480. }
  481. mi.err = unmarshalBytes(keyOut, nextBytes)
  482. return mi.err == nil
  483. }
  484. mi.err = errIterationAborted
  485. return false
  486. }
  487. // Err returns any encountered error.
  488. //
  489. // The method must be called after Next returns nil.
  490. func (mi *MapIterator) Err() error {
  491. return mi.err
  492. }
  493. // IsNotExist returns true if the error indicates that a
  494. // key doesn't exist.
  495. func IsNotExist(err error) bool {
  496. return errors.Cause(err) == unix.ENOENT
  497. }
  498. // IsIterationAborted returns true if the iteration was aborted.
  499. //
  500. // This occurs when keys are deleted from a hash map during iteration.
  501. func IsIterationAborted(err error) bool {
  502. return errors.Cause(err) == errIterationAborted
  503. }