• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &section) { 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 &section : 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