• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 #include "ebpf_splitter.h"
17 #include <cinttypes>
18 
19 namespace SysTuning {
20 namespace TraceStreamer {
21 // using namespace SysTuning::base;
22 using namespace SysTuning::EbpfStdtype;
SetEbpfDataOffset(uint64_t offset)23 void EbpfSplitter::SetEbpfDataOffset(uint64_t offset)
24 {
25     // 记录ebpf的1024头相对于文件的位置。
26     offsetOfEbpfDataInFile_ = offset;
27 }
28 
SetSpliteTimeRange(uint64_t splitFileMinTs,uint64_t splitFileMaxTs)29 void EbpfSplitter::SetSpliteTimeRange(uint64_t splitFileMinTs, uint64_t splitFileMaxTs)
30 {
31     splitFileMinTs_ = splitFileMinTs;
32     splitFileMaxTs_ = splitFileMaxTs;
33     TS_LOGI("splitFileMinTs_ = %" PRIu64 ", splitFileMaxTs_ = %" PRIu64 "", splitFileMinTs_, splitFileMaxTs_);
34 }
SplitEbpfHeader(std::deque<uint8_t> & dequeBuffer)35 bool EbpfSplitter::SplitEbpfHeader(std::deque<uint8_t>& dequeBuffer)
36 {
37     splitEbpfHeader_ = std::make_unique<EbpfDataHeader>();
38     std::copy_n(dequeBuffer.begin(), EbpfDataHeader::EBPF_DATA_HEADER_SIZE,
39                 reinterpret_cast<char*>(splitEbpfHeader_.get()));
40     if (splitEbpfHeader_->header.magic != EbpfDataHeader::HEADER_MAGIC) {
41         TS_LOGE("Get EBPF file header failed! magic = %" PRIx64 "", splitEbpfHeader_->header.magic);
42         return false;
43     }
44     if (splitEbpfHeader_->header.headSize != EbpfDataHeader::EBPF_DATA_HEADER_SIZE) {
45         TS_LOGE("Get ebpf file header failed! headSize = %u", splitEbpfHeader_->header.headSize);
46         return false;
47     }
48     TS_LOGI("EBPF data header : magic = %" PRIu64 ", headSize = %u, clock = %u, cmdline = %s",
49             splitEbpfHeader_->header.magic, splitEbpfHeader_->header.headSize, splitEbpfHeader_->header.clock,
50             splitEbpfHeader_->cmdline);
51     splittedLen_ += EbpfDataHeader::EBPF_DATA_HEADER_SIZE;
52     dequeBuffer.erase(dequeBuffer.begin(), dequeBuffer.begin() + EbpfDataHeader::EBPF_DATA_HEADER_SIZE);
53     return true;
54 }
55 
AddAndSplitEbpfData(std::deque<uint8_t> & dequeBuffer)56 bool EbpfSplitter::AddAndSplitEbpfData(std::deque<uint8_t>& dequeBuffer)
57 {
58     if (!splitEbpfHeader_) {
59         HtraceSplitResult ebpfHtraceHead = {.type = (int32_t)SplitDataDataType::SPLIT_FILE_DATA,
60                                             .buffer = {.address = reinterpret_cast<uint8_t*>(&profilerHeader_),
61                                                        .size = sizeof(ProfilerTraceFileHeader)}};
62         ebpfSplitResult_.emplace_back(ebpfHtraceHead);
63         if (dequeBuffer.size() >= EbpfDataHeader::EBPF_DATA_HEADER_SIZE) {
64             auto ret = SplitEbpfHeader(dequeBuffer);
65             HtraceSplitResult ebpfHead = {.type = (int32_t)SplitDataDataType::SPLIT_FILE_DATA,
66                                           .buffer = {.address = reinterpret_cast<uint8_t*>(splitEbpfHeader_.get()),
67                                                      .size = EbpfDataHeader::EBPF_DATA_HEADER_SIZE}};
68             ebpfSplitResult_.emplace_back(ebpfHead);
69             TS_ASSERT(ret);
70         } else {
71             return false;
72         }
73     }
74 
75     SplitEbpfBodyData(dequeBuffer);
76     uint64_t unUsedLength = profilerHeader_.data.length - sizeof(ProfilerTraceFileHeader) - splittedLen_;
77     if (unUsedLength < EBPF_TITLE_SIZE) {
78         profilerHeader_.data.length = usefulDataLen_ + sizeof(ProfilerTraceFileHeader) + sizeof(EbpfDataHeader);
79 
80         dequeBuffer.erase(dequeBuffer.begin(), dequeBuffer.begin() + unUsedLength);
81         return true;
82     }
83     return false;
84 }
AppendSplitOriginSegResult(uint32_t segLen)85 void EbpfSplitter::AppendSplitOriginSegResult(uint32_t segLen)
86 {
87     HtraceSplitResult publicDataOffset{.type = (int32_t)SplitDataDataType::SPLIT_FILE_JSON,
88                                        .originSeg = {.offset = offsetOfEbpfDataInFile_ + splittedLen_, .size = segLen}};
89     usefulDataLen_ += segLen;
90     ebpfSplitResult_.emplace_back(publicDataOffset);
91 }
SplitEbpfBodyData(std::deque<uint8_t> & dequeBuffer)92 void EbpfSplitter::SplitEbpfBodyData(std::deque<uint8_t>& dequeBuffer)
93 {
94     while (profilerHeader_.data.length - sizeof(ProfilerTraceFileHeader) - splittedLen_ > EBPF_TITLE_SIZE &&
95            dequeBuffer.size() > EBPF_TITLE_SIZE) {
96         EbpfTypeAndLength dataTitle;
97         std::copy_n(dequeBuffer.begin(), EBPF_TITLE_SIZE, reinterpret_cast<char*>(&dataTitle));
98         if (dataTitle.length + EBPF_TITLE_SIZE > dequeBuffer.size()) {
99             return;
100         }
101         auto segLen = EBPF_TITLE_SIZE + dataTitle.length;
102         switch (dataTitle.type) {
103             case ITEM_EVENT_MAPS:
104             case ITEM_SYMBOL_INFO:
105             case ITEM_EVENT_STR:
106             case ITEM_EVENT_KENEL_SYMBOL_INFO: {
107                 AppendSplitOriginSegResult(segLen);
108             } break;
109             case ITEM_EVENT_FS: {
110                 FsFixedHeader fsFixedHeader;
111                 AppendSplitResultWithFixedHeader(segLen, dequeBuffer, fsFixedHeader);
112             } break;
113             case ITEM_EVENT_VM: {
114                 PagedMemoryFixedHeader pagedMemoryFixedHeader;
115                 AppendSplitResultWithFixedHeader(segLen, dequeBuffer, pagedMemoryFixedHeader);
116             } break;
117             case ITEM_EVENT_BIO: {
118                 BIOFixedHeader bioFixedHeader;
119                 AppendSplitResultWithFixedHeader(segLen, dequeBuffer, bioFixedHeader);
120             } break;
121             default:
122                 TS_LOGI("Do not support EBPF type: %d, length: %d", dataTitle.type, dataTitle.length);
123         }
124         dequeBuffer.erase(dequeBuffer.begin(), dequeBuffer.begin() + segLen);
125         splittedLen_ += segLen;
126     }
127 }
128 } // namespace TraceStreamer
129 } // namespace SysTuning
130