1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef BPF_CONTROLLER_H
17#define BPF_CONTROLLER_H
18
19#include <iostream>
20
21#include <memory>
22#include <string>
23#include <functional>
24#include <vector>
25#include <functional>
26#include <set>
27
28#include "type_headers.h"
29#include "libbpf.h"
30#include "bpf_log_reader.h"
31#include "hhlog.h"
32#include "hiebpf.skel.h"
33#include "bpf_event_receiver.h"
34#include "hiebpf_data_file.h"
35
36enum HiebpfEventGroup:uint32_t {
37    // file system events start from 0x000
38    FS_GROUP_BASE = 0,
39    FS_GROUP_ALL = FS_GROUP_BASE,
40    FS_GROUP_OPEN,
41    FS_GROUP_READ,
42    FS_GROUP_WRITE,
43    FS_GROUP_CLOSE,
44    // memory events start from 0x100
45    MEM_GROUP_BASE = 0x100,
46    MEM_GROUP_ALL = MEM_GROUP_BASE,
47    // BIO  events start from 0x200
48    BIO_GROUP_BASE = 0x200,
49    BIO_GROUP_ALL = BIO_GROUP_BASE,
50};
51
52struct BPFConfig {
53    bool excludeTracer_ {true};
54    bool unwindStack_ {true};
55    __u32 dumpEvents_ {0};
56    __u32 traceDuration_ {0};
57    __u32 maxStackDepth_ {MAX_STACK_LIMIT};
58    __u32 epollTimeout_ {100};
59    __u32 pipelines_ {1}; // Numbers of pipeline channels that process data in user mode
60    std::string cmd_;
61    std::vector<pid_t> targetPids_ {};
62    std::set<HiebpfEventGroup> selectEventGroups_ {};
63    std::string outputFile_ {"/data/local/tmp/hiebpf.data"};
64    // loggers configs
65    __u32 BPFLogLevel_ {BPF_LOG_DEBUG};
66    int LIBBPFLogLevel_ {LIBBPF_DEBUG};
67    std::string BPFLogFile_ {"stdout"};
68    std::string LIBBPFLogFile_ {"stdout"};
69};
70
71class BPFController {
72public:
73    ~BPFController();
74    static std::unique_ptr<BPFController> MakeUnique(const struct BPFConfig& config);
75    int Start();
76    void Stop();
77
78    static int HandleEvent(void *ctx, void *data, size_t dataSize);
79    static int DumpEvent(void *ctx, void *data, size_t dataSize);
80
81    enum ConfigurationLimit:__u32 {
82        DUMP_EVENTS_LIMIT = 10000,
83        TRACE_DURATION_LIMIT = 3600,
84        MIN_PIPELINES_LIMIT = 1,
85    };
86
87private:
88    BPFController(const struct BPFConfig& config):config_ {config} {}
89    int VerifySelectEventGroups(const std::set<HiebpfEventGroup> &selectEventGroups);
90    int VerifyConfigurations();
91    int SetUpBPF();
92    int FilterProgByEvents();
93    void FilterFsGroup();
94    int ConfigureBPF();
95    int InitBPFVariables() const;
96    int FillTargetPidMap() const;
97    int ConfigBPFLogger();
98    int ConfigLIBBPFLogger() const;
99    int ConfigReceivers();
100    int32_t ConfigDlopenBPFProg();
101    uint64_t GetSymOffset(const std::string &path, const std::string &symbol);
102    std::weak_ptr<BPFEventReceiver> NextActiveReceiver();
103
104    int BPFEventLoopOnce() const
105    {
106        int err = ring_buffer__poll(rb_, config_.epollTimeout_);
107        if (err < 0) {
108            HHLOGE(true, "failed to poll BPF ring buffer: %s", strerror(-err));
109            return err;
110        }
111        return 0;
112    }
113
114    inline int StartBPFLogReader()
115    {
116        if (bpfLogReader_) {
117            return bpfLogReader_->Start();
118        }
119        return 0;
120    }
121
122    inline int StartReceivers()
123    {
124        if (receivers_.empty()) {
125            return 0;
126        }
127        for (__u32 k = 0; k < receivers_.size(); ++k) {
128            if (receivers_[k]->Start() != 0) {
129                return -1;
130            }
131        }
132        return 0;
133    }
134
135    static int LIBBPFPrintFunc(enum libbpf_print_level level, const char *format, va_list args);
136    static int DumpFSTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize);
137    static int DumpPFTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize);
138    static int DumpBIOTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize);
139    static int DumpSTRTraceEvent(void *data, size_t dataSize);
140
141    bool loopStop_ {false};
142    struct hiebpf_bpf* skel_ {nullptr};
143    std::unique_ptr<BPFLogReader> bpfLogReader_ {nullptr};
144    struct BPFConfig config_;
145    std::set<HiebpfEventGroup> selectEventGroups_ {};
146    struct ring_buffer* rb_ {nullptr};
147    std::shared_ptr<HiebpfDataFile> dataFile_ {nullptr};
148    std::vector<std::shared_ptr<BPFEventReceiver>> receivers_ {};
149    __u32 last_ {0};
150    __u64 *ips_ {nullptr};
151};
152
153#endif