From 57d7e472f22b2b2690a1f02d22e071cbd8140938 Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Mon, 8 May 2017 18:05:48 +0200 Subject: [PATCH] vendor: update gobpf This includes: https://github.com/iovisor/gobpf/pull/43 https://github.com/iovisor/gobpf/pull/44 --- vendor/github.com/iovisor/gobpf/elf/elf.go | 38 +++++++++++++++---- .../iovisor/gobpf/elf/elf_unsupported.go | 11 +++--- vendor/github.com/iovisor/gobpf/elf/perf.go | 35 +++++++++-------- vendor/manifest | 2 +- 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/vendor/github.com/iovisor/gobpf/elf/elf.go b/vendor/github.com/iovisor/gobpf/elf/elf.go index 4047136c..753bdd18 100644 --- a/vendor/github.com/iovisor/gobpf/elf/elf.go +++ b/vendor/github.com/iovisor/gobpf/elf/elf.go @@ -348,7 +348,14 @@ func (b *Module) relocate(data []byte, rdata []byte) error { } } -func (b *Module) Load() error { +type SectionParams struct { + PerfRingBufferPageCount int + SkipPerfMapInitialization bool +} + +// Load loads the BPF programs and BPF maps in the module. Each ELF section +// can optionally have parameters that changes how it is configured. +func (b *Module) Load(parameters map[string]SectionParams) error { if b.fileName != "" { fileReader, err := os.Open(b.fileName) if err != nil { @@ -541,10 +548,10 @@ func (b *Module) Load() error { } } - return b.initializePerfMaps() + return b.initializePerfMaps(parameters) } -func (b *Module) initializePerfMaps() error { +func (b *Module) initializePerfMaps(parameters map[string]SectionParams) error { for name, m := range b.maps { var cpu C.int = 0 @@ -552,6 +559,22 @@ func (b *Module) initializePerfMaps() error { continue } + pageSize := os.Getpagesize() + b.maps[name].pageCount = 8 // reasonable default + + sectionName := "maps/" + name + if params, ok := parameters[sectionName]; ok { + if params.SkipPerfMapInitialization { + continue + } + if params.PerfRingBufferPageCount > 0 { + if params.PerfRingBufferPageCount <= 0 || (params.PerfRingBufferPageCount&(params.PerfRingBufferPageCount-1)) != 0 { + return fmt.Errorf("number of pages (%d) must be stricly positive and a power of 2", params.PerfRingBufferPageCount) + } + b.maps[name].pageCount = params.PerfRingBufferPageCount + } + } + for { pmuFD, err := C.perf_event_open_map(-1 /* pid */, cpu /* cpu */, -1 /* group_fd */, C.PERF_FLAG_FD_CLOEXEC) if pmuFD < 0 { @@ -562,9 +585,7 @@ func (b *Module) initializePerfMaps() error { } // mmap - pageSize := os.Getpagesize() - pageCount := 8 - mmapSize := pageSize * (pageCount + 1) + mmapSize := pageSize * (b.maps[name].pageCount + 1) base, err := syscall.Mmap(int(pmuFD), 0, mmapSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) if err != nil { @@ -602,8 +623,9 @@ type Map struct { m *C.bpf_map // only for perf maps - pmuFDs []C.int - headers []*C.struct_perf_event_mmap_page + pmuFDs []C.int + headers []*C.struct_perf_event_mmap_page + pageCount int } func (b *Module) IterMaps() <-chan *Map { diff --git a/vendor/github.com/iovisor/gobpf/elf/elf_unsupported.go b/vendor/github.com/iovisor/gobpf/elf/elf_unsupported.go index 4c408e3f..a459d1ce 100644 --- a/vendor/github.com/iovisor/gobpf/elf/elf_unsupported.go +++ b/vendor/github.com/iovisor/gobpf/elf/elf_unsupported.go @@ -6,12 +6,13 @@ import ( "fmt" ) -func (b *Module) Load() error { - return fmt.Errorf("not supported") -} - // not supported; dummy struct type BPFKProbePerf struct{} +type SectionParams struct{} + +func (b *Module) Load(parameters map[string]SectionParams) error { + return fmt.Errorf("not supported") +} func NewBpfPerfEvent(fileName string) *BPFKProbePerf { // not supported @@ -22,7 +23,7 @@ func (b *BPFKProbePerf) Load() error { return fmt.Errorf("not supported") } -func (b *BPFKProbePerf) PollStart(mapName string, receiverChan chan []byte) { +func (b *BPFKProbePerf) PollStart(mapName string, receiverChan chan []byte, lostChan chan uint64) { // not supported return } diff --git a/vendor/github.com/iovisor/gobpf/elf/perf.go b/vendor/github.com/iovisor/gobpf/elf/perf.go index 2a9d467b..a81d8ed2 100644 --- a/vendor/github.com/iovisor/gobpf/elf/perf.go +++ b/vendor/github.com/iovisor/gobpf/elf/perf.go @@ -106,7 +106,9 @@ import "C" type PerfMap struct { name string program *Module + pageCount int receiverChan chan []byte + lostChan chan uint64 pollStop chan bool timestamp func(*[]byte) uint64 } @@ -118,8 +120,8 @@ type PerfEventSample struct { data byte // Size bytes of data } -func InitPerfMap(b *Module, mapName string, receiverChan chan []byte) (*PerfMap, error) { - _, ok := b.maps[mapName] +func InitPerfMap(b *Module, mapName string, receiverChan chan []byte, lostChan chan uint64) (*PerfMap, error) { + m, ok := b.maps[mapName] if !ok { return nil, fmt.Errorf("no map with name %s", mapName) } @@ -127,7 +129,9 @@ func InitPerfMap(b *Module, mapName string, receiverChan chan []byte) (*PerfMap, return &PerfMap{ name: mapName, program: b, + pageCount: m.pageCount, receiverChan: receiverChan, + lostChan: lostChan, pollStop: make(chan bool), }, nil } @@ -157,7 +161,6 @@ func (pm *PerfMap) PollStart() { go func() { cpuCount := len(m.pmuFDs) pageSize := os.Getpagesize() - pageCount := 8 state := C.struct_read_state{} for { @@ -168,59 +171,61 @@ func (pm *PerfMap) PollStart() { perfEventPoll(m.pmuFDs) } + harvestLoop: for { var harvestCount C.int beforeHarvest := nowNanoseconds() for cpu := 0; cpu < cpuCount; cpu++ { + ringBufferLoop: for { var sample *PerfEventSample var lost *PerfEventLost - ok := C.perf_event_read(C.int(pageCount), C.int(pageSize), + ok := C.perf_event_read(C.int(pm.pageCount), C.int(pageSize), unsafe.Pointer(&state), unsafe.Pointer(m.headers[cpu]), unsafe.Pointer(&sample), unsafe.Pointer(&lost)) switch ok { case 0: - break // nothing to read + break ringBufferLoop // nothing to read case C.PERF_RECORD_SAMPLE: size := sample.Size - 4 b := C.GoBytes(unsafe.Pointer(&sample.data), C.int(size)) incoming.bytesArray = append(incoming.bytesArray, b) harvestCount++ if pm.timestamp == nil { - continue + continue ringBufferLoop } if incoming.timestamp(&b) > beforeHarvest { // see comment below - break - } else { - continue + break ringBufferLoop } case C.PERF_RECORD_LOST: + if pm.lostChan != nil { + pm.lostChan <- lost.Lost + } default: - // TODO: handle lost/unknown events? + // ignore unknown events } - break } } if incoming.timestamp != nil { sort.Sort(incoming) } - for i := 0; i < incoming.Len(); i++ { + for incoming.Len() > 0 { if incoming.timestamp != nil && incoming.timestamp(&incoming.bytesArray[0]) > beforeHarvest { // This record has been sent after the beginning of the harvest. Stop // processing here to keep the order. "incoming" is sorted, so the next // elements also must not be processed now. - break + break harvestLoop } pm.receiverChan <- incoming.bytesArray[0] // remove first element incoming.bytesArray = incoming.bytesArray[1:] } if harvestCount == 0 && len(incoming.bytesArray) == 0 { - break + break harvestLoop } } } @@ -265,7 +270,7 @@ func (a OrderedBytesArray) Swap(i, j int) { } func (a OrderedBytesArray) Less(i, j int) bool { - return *(*C.uint64_t)(unsafe.Pointer(&a.bytesArray[i][0])) < *(*C.uint64_t)(unsafe.Pointer(&a.bytesArray[j][0])) + return a.timestamp(&a.bytesArray[i]) < a.timestamp(&a.bytesArray[j]) } // Matching 'struct perf_event_header in diff --git a/vendor/manifest b/vendor/manifest index 730426eb..c2b092d1 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -5,7 +5,7 @@ "importpath": "github.com/iovisor/gobpf/elf", "repository": "https://github.com/iovisor/gobpf", "vcs": "git", - "revision": "65e4048660d6c4339ebae113ac55b1af6f01305d", + "revision": "7373736877197caa9273bb731e90fea3b3d903cc", "branch": "master", "path": "/elf", "notests": true