github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/pin.go (about) 1 package gobpfld 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path" 8 "strings" 9 "unsafe" 10 11 "github.com/dylandreimerink/gobpfld/bpfsys" 12 "github.com/dylandreimerink/gobpfld/internal/cstr" 13 ) 14 15 // BPFSysPath is the path to the bpf FS used to pin objects to 16 const BPFSysPath = "/sys/fs/bpf/" 17 18 // PinFD pins an eBPF object(map, program, link) identified by the given `fd` to the given `relativePath` 19 // relative to the `BPFSysPath` on the BPF FS. 20 // 21 // This function is exposed so custom program or map implementations can use outside of this library. 22 // However, it is recommendd to use the BPFProgram.Pin and AbstractMap.Pin functions if gobpfld types are used. 23 func PinFD(relativePath string, fd bpfsys.BPFfd) error { 24 sysPath := fmt.Sprint(BPFSysPath, relativePath) 25 26 // Create directories if any are missing 27 err := os.MkdirAll(path.Dir(sysPath), 0644) 28 if err != nil { 29 return fmt.Errorf("error while making directories: %w, make sure bpffs is mounted at '%s'", err, BPFSysPath) 30 } 31 32 cPath := cstr.StringToCStrBytes(sysPath) 33 34 err = bpfsys.ObjectPin(&bpfsys.BPFAttrObj{ 35 BPFfd: fd, 36 Pathname: uintptr(unsafe.Pointer(&cPath[0])), 37 }) 38 if err != nil { 39 return fmt.Errorf("bpf syscall error: %w", err) 40 } 41 42 return nil 43 } 44 45 // UnpinFD gets the fd of an eBPF object(map, program, link) which is pinned at the given `relativePath` 46 // relative to the `BPFSysPath` on the BPF FS. 47 // If `deletePin` is true, this function will remove the pin from the BPF FS after successfully getting it. 48 // 49 // This function is exposed so custom program or map implementations can use outside of this library. 50 // However, it is recommend to use the BPFProgram.Unpin and AbstractMap.Unpin functions if gobpfld types are used. 51 // 52 // TODO make this function unexported and create an UnpinMap and UnpinProgram function which will automatically recreate 53 // the proper maps. (also necessary to handle map registration properly) 54 func UnpinFD(relativePath string, deletePin bool) (bpfsys.BPFfd, error) { 55 sysPath := fmt.Sprint(BPFSysPath, relativePath) 56 cpath := cstr.StringToCStrBytes(sysPath) 57 58 fd, err := bpfsys.ObjectGet(&bpfsys.BPFAttrObj{ 59 Pathname: uintptr(unsafe.Pointer(&cpath[0])), 60 }) 61 if err != nil { 62 return fd, fmt.Errorf("bpf obj get syscall error: %w", err) 63 } 64 65 if deletePin { 66 err = os.Remove(sysPath) 67 if err != nil { 68 return fd, fmt.Errorf("error while deleting pin: %w", err) 69 } 70 71 // Get the directories in the relative path 72 dirs := path.Dir(relativePath) 73 if dirs == "." || dirs == "/" { 74 dirs = "" 75 } 76 77 // get array of dirs 78 relDirs := strings.Split(dirs, string(os.PathSeparator)) 79 // If there is at least one directory 80 if relDirs[0] != "" { 81 // Loop over all directories 82 for _, dir := range relDirs { 83 dirPath := fmt.Sprint(BPFSysPath, dir) 84 files, err := ioutil.ReadDir(dirPath) 85 if err != nil { 86 return fd, fmt.Errorf("error while reading dir: %w", err) 87 } 88 89 // If the dir is empty, remove it 90 if len(files) == 0 { 91 err = os.Remove(dirPath) 92 if err != nil { 93 return fd, fmt.Errorf("error while deleting empty dir: %w", err) 94 } 95 } 96 } 97 } 98 } 99 100 return fd, nil 101 }