diff --git a/bpf/headers/feature_switch.h b/bpf/headers/feature_switch.h deleted file mode 100644 index 0397f5e8..00000000 --- a/bpf/headers/feature_switch.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -enum insp_switch_key{ - //Add enum in pkg/exporter/probe/feature-switch.go also - enable_packetloss_stack, - enable_flow_label_port, - enable_tcpretrans_stack -}; - -//const enum insp_switch_key *unused_insp_switch_key __attribute__((unused)); - -struct { - //__uint(type, BPF_MAP_TYPE_ARRAY); - __uint(type, BPF_MAP_TYPE_HASH); - __uint(key_size, sizeof(unsigned char)); - __uint(value_size, sizeof(bool)); - __uint(max_entries, 128); -} insp_feature_switch SEC(".maps"); - diff --git a/bpf/packetloss.c b/bpf/packetloss.c index c3db10c8..5c6c97b1 100644 --- a/bpf/packetloss.c +++ b/bpf/packetloss.c @@ -6,7 +6,6 @@ #include #include #include -#include struct kfree_skb_args { /* The first 8 bytes is not allowed to read */ @@ -24,6 +23,7 @@ struct insp_pl_event_t { }; const struct insp_pl_event_t *unused_insp_pl_event_t __attribute__((unused)); +const volatile u8 enable_packetloss_stack = 0; struct { __uint(type, BPF_MAP_TYPE_STACK_TRACE); @@ -40,14 +40,11 @@ SEC("tracepoint/skb/kfree_skb") int kfree_skb(struct kfree_skb_args *args) { struct sk_buff *skb = (struct sk_buff *)args->skb; struct insp_pl_event_t event = {0}; - enum insp_switch_key switch_key = enable_packetloss_stack; - set_tuple(skb, &event.tuple); event.location = (u64)args->location; - bool *enable = bpf_map_lookup_elem(&insp_feature_switch, &switch_key); - if (enable && *enable){ + if (enable_packetloss_stack){ event.stack_id = bpf_get_stackid(args, &insp_pl_stack, KERN_STACKID_FLAGS); } diff --git a/deploy/net-exporter-config.yaml b/deploy/net-exporter-config.yaml index 5d535e47..8455ce61 100644 --- a/deploy/net-exporter-config.yaml +++ b/deploy/net-exporter-config.yaml @@ -14,13 +14,19 @@ metrics: - name: udp - name: kernellatency - name: packetloss + args: + enableStack: false - name: flow + args: + enablePortInLabel: false - name: tcpretrans event: probes: - name: biolatency - name: kernellatency - name: packetloss + args: + enableStack: false - name: tcpreset - name: tcpretrans sinks: diff --git a/pkg/exporter/probe/feature-switch.go b/pkg/exporter/probe/feature-switch.go deleted file mode 100644 index 0218a25d..00000000 --- a/pkg/exporter/probe/feature-switch.go +++ /dev/null @@ -1,45 +0,0 @@ -package probe - -import ( - "github.com/cilium/ebpf" - "sync" -) - -type FeatureSwitch uint32 - -const ( - EnablePacketLossStack = iota - EnableFlowLabelPort - EnableTcpRetransStack -) - -var lock sync.Mutex -var switchMap *ebpf.Map - -const FeatureSwitchMapName = "insp_feature_switch" - -func LoadBPFSwitchMap() (*ebpf.Map, error) { - lock.Lock() - defer lock.Unlock() - if switchMap != nil { - return switchMap, nil - } - - spec := ebpf.MapSpec{ - Name: FeatureSwitchMapName, - Type: ebpf.Hash, - KeySize: 1, - ValueSize: 1, - MaxEntries: 128, - } - var err error - switchMap, err = ebpf.NewMap(&spec) - if err != nil { - return nil, err - } - return switchMap, nil -} - -func UpdateSwitch(featureSwitch FeatureSwitch, val uint8) error { - return switchMap.Update(uint8(featureSwitch), val, ebpf.UpdateAny) -} diff --git a/pkg/exporter/probe/tracepacketloss/packetloss.go b/pkg/exporter/probe/tracepacketloss/packetloss.go index 91648203..f81b8193 100644 --- a/pkg/exporter/probe/tracepacketloss/packetloss.go +++ b/pkg/exporter/probe/tracepacketloss/packetloss.go @@ -191,19 +191,24 @@ func (p *packetLossProbe) stop(probeType probe.Type) error { p.probeConfig[probeType] = nil if probeType == probe.ProbeTypeEvent { - if p.perfReader != nil { - p.perfReader.Close() - } + p.closePerfReader() } if p.probeCount() == 0 { - return p.cleanup() + p.cleanup() } return nil } -func (p *packetLossProbe) cleanup() error { +func (p *packetLossProbe) closePerfReader() { + if p.perfReader != nil { + p.perfReader.Close() + p.perfReader = nil + } +} + +func (p *packetLossProbe) cleanup() { for _, link := range p.links { link.Close() } @@ -212,22 +217,9 @@ func (p *packetLossProbe) cleanup() error { p.objs.Close() - return nil -} - -func (p *packetLossProbe) updateSwitch() error { - enableStack := uint8(0) - for _, cfg := range p.probeConfig { - log.Infof("cfg: %v", cfg) - if cfg != nil && cfg.enableStack { - enableStack = 1 - } - } - log.Infof("%s update feature switch, set enablePacketLossStack to %d", probeName, enableStack) - return probe.UpdateSwitch(probe.EnablePacketLossStack, enableStack) } -func (p *packetLossProbe) start(probeType probe.Type, cfg *probeConfig) (err error) { +func (p *packetLossProbe) start(probeType probe.Type, cfg *probeConfig) error { p.lock.Lock() defer p.lock.Unlock() @@ -236,26 +228,42 @@ func (p *packetLossProbe) start(probeType probe.Type, cfg *probeConfig) (err err } p.probeConfig[probeType] = cfg - if p.probeCount() == 1 { - if err = p.loadAndAttachBPF(); err != nil { - log.Errorf("%s failed load and attach bpf, err: %v", probeName, err) - _ = p.cleanup() - return + + if err := p.reinstallBPFLocked(); err != nil { + return fmt.Errorf("%s failed install ebpf: %w", probeName, err) + } + + var err error + + if probeType == probe.ProbeTypeEvent { + p.perfReader, err = perf.NewReader(p.objs.bpfMaps.InspPlEvent, int(unsafe.Sizeof(bpfInspPlEventT{}))) + if err != nil { + log.Errorf("%s error create perf reader, err: %v", probeName, err) + return err } + + go p.perfLoop() } - if err = p.updateSwitch(); err != nil { - log.Errorf("%s failed update feature switch, err: %v", probeName, err) - _ = p.cleanup() - return + return nil +} + +func (p *packetLossProbe) reinstallBPFLocked() error { + p.closePerfReader() + p.cleanup() + + if err := p.loadAndAttachBPF(); err != nil { + log.Errorf("%s failed load and attach bpf, err: %v", probeName, err) + p.cleanup() + return err } - if probeType == probe.ProbeTypeEvent { + if p.probeConfig[probe.ProbeTypeEvent] != nil { + var err error p.perfReader, err = perf.NewReader(p.objs.bpfMaps.InspPlEvent, int(unsafe.Sizeof(bpfInspPlEventT{}))) if err != nil { log.Errorf("%s error create perf reader, err: %v", probeName, err) - _ = p.stop(probeType) - return + return err } go p.perfLoop() @@ -264,35 +272,47 @@ func (p *packetLossProbe) start(probeType probe.Type, cfg *probeConfig) (err err return nil } +func (p *packetLossProbe) enableStack() bool { + for _, cfg := range p.probeConfig { + if cfg != nil && cfg.enableStack { + return true + } + } + return false +} + func (p *packetLossProbe) loadAndAttachBPF() error { // Allow the current process to lock memory for eBPF resources. if err := rlimit.RemoveMemlock(); err != nil { return fmt.Errorf("remove limit failed: %s", err.Error()) } - switchMap, err := probe.LoadBPFSwitchMap() + spec, err := loadBpf() if err != nil { - return fmt.Errorf("failed load switch map:%v", err) + return fmt.Errorf("failed loading bpf: %w", err) } - opts := ebpf.CollectionOptions{ - MapReplacements: map[string]*ebpf.Map{ - probe.FeatureSwitchMapName: switchMap, - }, + if p.enableStack() { + m := map[string]interface{}{ + "enable_packetloss_stack": uint8(1), + } + if err := spec.RewriteConstants(m); err != nil { + return fmt.Errorf("failed rewrite constants: %w", err) + } } - opts.Programs = ebpf.ProgramOptions{ - KernelTypes: bpfutil.LoadBTFSpecOrNil(), + opts := ebpf.CollectionOptions{ + Programs: ebpf.ProgramOptions{ + KernelTypes: bpfutil.LoadBTFSpecOrNil(), + }, } - - // Load pre-compiled programs and maps into the kernel. - if err := loadBpfObjects(&p.objs, &opts); err != nil { + if err := spec.LoadAndAssign(p.objs, &opts); err != nil { return fmt.Errorf("loading objects: %s", err.Error()) } pl, err := link.Tracepoint("skb", "kfree_skb", p.objs.KfreeSkb, &link.TracepointOptions{}) if err != nil { - return fmt.Errorf("link tracepoint kfree_skb failed: %s", err.Error()) + return fmt.Errorf("link tracepoint kfree_skb failed: %w", err) } p.links = append(p.links, pl) return nil