1 /*
2 * Copyright (c) 2022 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 #ifdef ENABLE_ELFIO
17 #include "bpf_map_creator.h"
18
19 #include <algorithm>
20 #endif
21
22 namespace OHOS {
23 namespace Bpf {
24 #ifdef ENABLE_ELFIO
CreateMaps(BpfMapData * maps,int32_t nrMaps)25 bool BpfMapCreator::CreateMaps(BpfMapData *maps, int32_t nrMaps)
26 {
27 for (int32_t i = 0; i < nrMaps; i++) {
28 int32_t numaNode = (maps[i].def.mapFlags & BPF_F_NUMA_NODE) ? maps[i].def.numaNode : -1;
29 mapFd_[i] = BpfCreateMapNode(static_cast<bpf_map_type>(maps[i].def.type), maps[i].name, maps[i].def.keySize,
30 maps[i].def.valueSize, maps[i].def.maxEntries, maps[i].def.mapFlags, numaNode);
31 if (mapFd_[i] < 0) {
32 NETNATIVE_LOGE("Failed to create map %{public}d (%{public}s): %{public}d %{public}s", i,
33 maps[i].name.c_str(), errno, strerror(errno));
34 return false;
35 }
36 maps[i].fd = mapFd_[i];
37
38 std::string mapPinLocation = std::string("/sys/fs/bpf/netsys_") + maps[i].name;
39 if (access(mapPinLocation.c_str(), F_OK) == 0) {
40 NETNATIVE_LOGI("map: %{public}s has already been pinned", mapPinLocation.c_str());
41 } else {
42 if (SysBpfObjPin(mapFd_[i], mapPinLocation)) {
43 NETNATIVE_LOGE("Failed to pin map: %{public}s, errno = %{public}d", mapPinLocation.c_str(), errno);
44 return false;
45 }
46 }
47 }
48
49 return true;
50 }
51
LoadElfMapsSection(BpfMapData * maps,const ELFIO::elfio & elfio) const52 int32_t BpfMapCreator::LoadElfMapsSection(BpfMapData *maps, const ELFIO::elfio &elfio) const
53 {
54 ELFIO::section *mapsSection = nullptr;
55
56 const auto &it = std::find_if(elfio.sections.begin(), elfio.sections.end(),
57 [](const auto §ion) { return section->get_name() == "maps"; });
58
59 if (it == elfio.sections.end()) {
60 NETNATIVE_LOGE("Failed to get maps section");
61 return 0;
62 }
63 mapsSection = it;
64 auto defs = reinterpret_cast<const BpfLoadMapDef *>(mapsSection->get_data());
65 auto nrMaps = mapsSection->get_size() / sizeof(BpfLoadMapDef);
66 for (int32_t i = 0; i < nrMaps; i++) {
67 maps[i].def = defs[i];
68 }
69
70 int32_t mapIndex = 0;
71 for (const auto §ion : elfio.sections) {
72 if (SHT_SYMTAB == section->get_type() || SHT_DYNSYM == section->get_type()) {
73 ELFIO::symbol_section_accessor symbols(elfio, section);
74 for (ELFIO::Elf_Xword i = 0; i < symbols.get_symbols_num(); i++) {
75 std::string name;
76 ELFIO::Elf64_Addr value = 0;
77 ELFIO::Elf_Xword size = 0;
78 unsigned char bind = 0;
79 unsigned char type = 0;
80 ELFIO::Elf_Half elfSection = 0;
81 unsigned char other = 0;
82 symbols.get_symbol(i, name, value, size, bind, type, elfSection, other);
83 if (type == STT_OBJECT && name.find("_map") != std::string::npos) {
84 maps[mapIndex].name = name;
85 NETNATIVE_LOGI("maps[%{public}d].name = %{public}s", mapIndex, maps[mapIndex].name.c_str());
86 mapIndex++;
87 continue;
88 }
89 }
90 }
91 }
92 return nrMaps;
93 }
94
BpfCreateMapNode(bpf_map_type mapType,std::string & name,int32_t keySize,int32_t valueSize,int32_t maxEntries,uint32_t mapFlags,int32_t node) const95 int32_t BpfMapCreator::BpfCreateMapNode(bpf_map_type mapType, std::string &name, int32_t keySize, int32_t valueSize,
96 int32_t maxEntries, uint32_t mapFlags, int32_t node) const
97 {
98 BpfCreateMapAttr mapAttr = {};
99 mapAttr.name = name;
100 mapAttr.mapType = mapType;
101 mapAttr.mapFlags = mapFlags;
102 mapAttr.keySize = keySize;
103 mapAttr.valueSize = valueSize;
104 mapAttr.maxEntries = maxEntries;
105 if (node >= 0) {
106 mapAttr.numaNode = node;
107 mapAttr.mapFlags |= BPF_F_NUMA_NODE;
108 }
109
110 return BpfCreateMapXattr(&mapAttr);
111 }
112
BpfCreateMapXattr(const BpfCreateMapAttr * createAttr) const113 int32_t BpfMapCreator::BpfCreateMapXattr(const BpfCreateMapAttr *createAttr) const
114 {
115 bpf_attr attr;
116
117 (void)memset_s(&attr, sizeof(attr), '\0', sizeof(attr));
118
119 attr.map_type = createAttr->mapType;
120 attr.key_size = createAttr->keySize;
121 attr.value_size = createAttr->valueSize;
122 attr.max_entries = createAttr->maxEntries;
123 attr.map_flags = createAttr->mapFlags;
124 if (!createAttr->name.empty()) {
125 createAttr->name.copy(
126 attr.map_name,
127 (createAttr->name.size() < (BPF_OBJ_NAME_LEN - 1) ? createAttr->name.size() : (BPF_OBJ_NAME_LEN - 1)));
128 }
129
130 attr.numa_node = createAttr->numaNode;
131 attr.btf_fd = createAttr->btfFd;
132 attr.btf_key_type_id = createAttr->btfKeyTypeId;
133 attr.btf_value_type_id = createAttr->btfValueTypeId;
134 attr.map_ifindex = createAttr->mapIfindex;
135 attr.inner_map_fd = createAttr->innerMapFd;
136
137 return SysBpf(BPF_MAP_CREATE, &attr, sizeof(attr));
138 }
139 #endif
140 } // namespace Bpf
141 } // namespace OHOS
142