func TracepointAttach()

in pkg/tracepoint/tracepoint.go [32:93]


func TracepointAttach(progFD int, subSystem, eventName string) error {

	if progFD <= 0 {
		log.Infof("Invalid BPF prog FD %d", progFD)
		return fmt.Errorf("invalid BPF prog FD %d", progFD)

	}

	if len(subSystem) == 0 || len(eventName) == 0 {
		return fmt.Errorf("invalid Arguement")
	}

	//Get the TP ID
	tracepointIDpath := fmt.Sprintf("%s/%s/%s/id", constdef.TRACEPOINT_EVENTS, subSystem, eventName)
	data, err := os.ReadFile(tracepointIDpath)
	if err != nil {
		log.Errorf("unable to read the tracepointID: %v", err)
		return err
	}
	id := strings.TrimSpace(string(data))
	eventID, err := strconv.Atoi(id)
	if err != nil {
		log.Errorf("invalid ID during parsing: %s - %w", id, err)
		return err
	}

	log.Infof("Got eventID %d", eventID)

	attr := unix.PerfEventAttr{
		Type:   unix.PERF_TYPE_TRACEPOINT,
		Sample: 1,
		Wakeup: 1,
		Config: uint64(eventID),
	}
	attr.Size = uint32(unsafe.Sizeof(attr))

	/*
	 * Ref : https://man7.org/linux/man-pages/man2/perf_event_open.2.html
	 * pid = -1 and cpu = 0 [This measures all processes/threads on the specified CPU]
	 * group_fd = -1 Creates event group with leader first.
	 */
	fd, err := unix.PerfEventOpen(&attr, -1, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
	if err != nil {
		log.Errorf("failed to open perf event %v", err)
		return err
	}

	log.Infof("Attach bpf program to perf event Prog FD %d Event FD %d", progFD, fd)

	if _, _, err := unix.Syscall(unix.SYS_IOCTL, uintptr(int(fd)), uintptr(uint(unix.PERF_EVENT_IOC_SET_BPF)), uintptr(progFD)); err != 0 {
		log.Errorf("error attaching bpf program to perf event: %v", err)
		return err
	}

	if _, _, err := unix.Syscall(unix.SYS_IOCTL, uintptr(int(fd)), uintptr(uint(unix.PERF_EVENT_IOC_ENABLE)), 0); err != 0 {
		log.Errorf("error enabling perf event: %v", err)
		return err
	}

	log.Infof("Tracepoint attach done!!! %d", fd)
	return nil
}