func (bpf *Module) LoadNet(name string) (int, error) {
	return bpf.Load(name, C.BPF_PROG_TYPE_SCHED_ACT, 0, 0)
}
LoadNet loads a program of type BPF_PROG_TYPE_SCHED_ACT.
package bcc
import (
	"fmt"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"syscall"
	"unsafe"
	"github.com/iovisor/gobpf/pkg/cpuonline"
)
import "C"
type Module struct {
	p              unsafe.Pointer
	funcs          map[string]int
	kprobes        map[string]int
	uprobes        map[string]int
	tracepoints    map[string]int
	rawTracepoints map[string]int
	perfEvents     map[string][]int
}
type compileRequest struct {
	code   string
	cflags []string
	rspCh  chan *Module
}
const (
	BPF_PROBE_ENTRY = iota
	BPF_PROBE_RETURN
)
const (
	XDP_FLAGS_UPDATE_IF_NOEXIST = uint32(1) << iota
	XDP_FLAGS_SKB_MODE
	XDP_FLAGS_DRV_MODE
	XDP_FLAGS_HW_MODE
	XDP_FLAGS_MODES = XDP_FLAGS_SKB_MODE | XDP_FLAGS_DRV_MODE | XDP_FLAGS_HW_MODE
	XDP_FLAGS_MASK  = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_MODES
)
var (
	defaultCflags []string
	compileCh     chan compileRequest
	bpfInitOnce   sync.Once
)
func bpfInit() {
	defaultCflags = []string{
		fmt.Sprintf("-DNUMCPUS=%d", runtime.NumCPU()),
	}
	compileCh = make(chan compileRequest)
	go compile()
}
func newModule(code string, cflags []string) *Module {
	cflagsC := make([]*C.char, len(defaultCflags)+len(cflags))
	defer func() {
		for _, cflag := range cflagsC {
			C.free(unsafe.Pointer(cflag))
		}
	}()
	for i, cflag := range cflags {
		cflagsC[i] = C.CString(cflag)
	}
	for i, cflag := range defaultCflags {
		cflagsC[len(cflags)+i] = C.CString(cflag)
	}
	cs := C.CString(code)
	defer C.free(unsafe.Pointer(cs))
	c := C.bpf_module_create_c_from_string(cs, 2, (**C.char)(&cflagsC[0]), C.int(len(cflagsC)), (C.bool)(true))
	if c == nil {
		return nil
	}
	return &Module{
		p:              c,
		funcs:          make(map[string]int),
		kprobes:        make(map[string]int),
		uprobes:        make(map[string]int),
		tracepoints:    make(map[string]int),
		rawTracepoints: make(map[string]int),
		perfEvents:     make(map[string][]int),
	}
}
func NewModule(code string, cflags []string) *Module {
	bpfInitOnce.Do(bpfInit)
	ch := make(chan *Module)
	compileCh <- compileRequest{code, cflags, ch}
	return <-ch
}
func compile() {
	for {
		req := <-compileCh
		req.rspCh <- newModule(req.code, req.cflags)
	}
}
func (bpf *Module) Close() {
	C.bpf_module_destroy(bpf.p)
	for k, v := range bpf.kprobes {
		C.bpf_close_perf_event_fd((C.int)(v))
		evNameCS := C.CString(k)
		C.bpf_detach_kprobe(evNameCS)
		C.free(unsafe.Pointer(evNameCS))
	}
	for k, v := range bpf.uprobes {
		C.bpf_close_perf_event_fd((C.int)(v))
		evNameCS := C.CString(k)
		C.bpf_detach_uprobe(evNameCS)
		C.free(unsafe.Pointer(evNameCS))
	}
	for k, v := range bpf.tracepoints {
		C.bpf_close_perf_event_fd((C.int)(v))
		parts := strings.SplitN(k, ":", 2)
		tpCategoryCS := C.CString(parts[0])
		tpNameCS := C.CString(parts[1])
		C.bpf_detach_tracepoint(tpCategoryCS, tpNameCS)
		C.free(unsafe.Pointer(tpCategoryCS))
		C.free(unsafe.Pointer(tpNameCS))
	}
	for _, vs := range bpf.perfEvents {
		for _, v := range vs {
			C.bpf_close_perf_event_fd((C.int)(v))
		}
	}
	for _, fd := range bpf.funcs {
		syscall.Close(fd)
	}
}
func (bpf *Module) GetProgramTag(fd int) (tag uint64, err error) {
	_, err = C.bpf_prog_get_tag(C.int(fd), (*C.ulonglong)(unsafe.Pointer(&tag)))
	return tag, err
}