P4C
The P4 Compiler
Loading...
Searching...
No Matches
ebpf/target.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef BACKENDS_EBPF_TARGET_H_
18#define BACKENDS_EBPF_TARGET_H_
19
20#include "frontends/p4/typeMap.h"
21#include "ir/ir.h"
22#include "lib/cstring.h"
23#include "lib/error.h"
24#include "lib/exceptions.h"
25#include "lib/sourceCodeBuilder.h"
26
29
30namespace P4::EBPF {
31
32using namespace P4::literals;
33
34enum TableKind {
35 TableHash,
36 TableArray,
37 TablePerCPUArray,
38 TableProgArray,
39 TableLPMTrie, // Longest prefix match trie.
40 TableHashLRU,
41 TableDevmap
42};
43
44class Target {
45 protected:
46 explicit Target(cstring name) : name(name) {}
47 Target() = delete;
48 virtual ~Target() {}
49
50 public:
51 const cstring name;
52
53 virtual void emitLicense(Util::SourceCodeBuilder *builder, cstring license) const = 0;
54 virtual void emitCodeSection(Util::SourceCodeBuilder *builder, cstring sectionName) const = 0;
55 virtual void emitIncludes(Util::SourceCodeBuilder *builder) const = 0;
56 virtual void emitResizeBuffer(Util::SourceCodeBuilder *builder, cstring buffer,
57 cstring offsetVar) const = 0;
58 virtual void emitTableLookup(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
59 cstring value) const = 0;
60 virtual void emitTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
61 cstring value) const = 0;
62 virtual void emitUserTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
63 cstring value) const = 0;
64 virtual void emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName,
65 TableKind tableKind, cstring keyType, cstring valueType,
66 unsigned size) const = 0;
67 virtual void emitTableDeclSpinlock(Util::SourceCodeBuilder *builder, cstring tblName,
68 TableKind tableKind, cstring keyType, cstring valueType,
69 unsigned size) const {
70 (void)builder;
71 (void)tblName;
72 (void)tableKind;
73 (void)keyType;
74 (void)valueType;
75 (void)size;
76 ::P4::error(ErrorType::ERR_UNSUPPORTED,
77 "emitTableDeclSpinlock is not supported on %1% target", name);
78 }
81 virtual void emitMapInMapDecl(Util::SourceCodeBuilder *builder, cstring innerName,
82 TableKind innerTableKind, cstring innerKeyType,
83 cstring innerValueType, unsigned innerSize, cstring outerName,
84 TableKind outerTableKind, cstring outerKeyType,
85 unsigned outerSize) const {
86 (void)builder;
87 (void)innerName;
88 (void)innerTableKind;
89 (void)innerKeyType;
90 (void)innerValueType;
91 (void)innerSize;
92 (void)outerName;
93 (void)outerTableKind;
94 (void)outerKeyType;
95 (void)outerSize;
96 ::P4::error(ErrorType::ERR_UNSUPPORTED, "emitMapInMapDecl is not supported on %1% target",
97 name);
98 }
99 virtual void emitMain(Util::SourceCodeBuilder *builder, cstring functionName,
100 cstring argName) const = 0;
101 virtual cstring dataOffset(cstring base) const = 0;
102 virtual cstring dataEnd(cstring base) const = 0;
103 virtual cstring dataLength(cstring base) const = 0;
104 virtual cstring forwardReturnCode() const = 0;
105 virtual cstring dropReturnCode() const = 0;
106 virtual cstring abortReturnCode() const = 0;
107 // Path on /sys filesystem where maps are stored
108 virtual cstring sysMapPath() const = 0;
109 virtual cstring packetDescriptorType() const = 0;
110
111 virtual void emitPreamble(Util::SourceCodeBuilder *builder) const;
123 virtual void emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format, int argc,
124 ...) const;
125 virtual void emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format) const;
126};
127
131 private:
132 mutable unsigned int innerMapIndex;
133
134 cstring getBPFMapType(TableKind kind) const {
135 if (kind == TableHash) {
136 return "BPF_MAP_TYPE_HASH"_cs;
137 } else if (kind == TableArray) {
138 return "BPF_MAP_TYPE_ARRAY"_cs;
139 } else if (kind == TablePerCPUArray) {
140 return "BPF_MAP_TYPE_PERCPU_ARRAY"_cs;
141 } else if (kind == TableLPMTrie) {
142 return "BPF_MAP_TYPE_LPM_TRIE"_cs;
143 } else if (kind == TableHashLRU) {
144 return "BPF_MAP_TYPE_LRU_HASH"_cs;
145 } else if (kind == TableProgArray) {
146 return "BPF_MAP_TYPE_PROG_ARRAY"_cs;
147 } else if (kind == TableDevmap) {
148 return "BPF_MAP_TYPE_DEVMAP"_cs;
149 }
150 BUG("Unknown table kind");
151 }
152
153 protected:
154 bool emitTraceMessages;
155
156 public:
157 explicit KernelSamplesTarget(bool emitTrace = false, cstring name = "Linux kernel"_cs)
158 : Target(name), innerMapIndex(0), emitTraceMessages(emitTrace) {}
159
160 void emitLicense(Util::SourceCodeBuilder *builder, cstring license) const override;
161 void emitCodeSection(Util::SourceCodeBuilder *builder, cstring sectionName) const override;
162 void emitIncludes(Util::SourceCodeBuilder *builder) const override;
163 void emitResizeBuffer(Util::SourceCodeBuilder *builder, cstring buffer,
164 cstring offsetVar) const override;
165 void emitTableLookup(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
166 cstring value) const override;
167 void emitTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
168 cstring value) const override;
169 void emitUserTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
170 cstring value) const override;
171 void emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName, TableKind tableKind,
172 cstring keyType, cstring valueType, unsigned size) const override;
173 void emitTableDeclSpinlock(Util::SourceCodeBuilder *builder, cstring tblName,
174 TableKind tableKind, cstring keyType, cstring valueType,
175 unsigned size) const override;
176 void emitMapInMapDecl(Util::SourceCodeBuilder *builder, cstring innerName,
177 TableKind innerTableKind, cstring innerKeyType, cstring innerValueType,
178 unsigned innerSize, cstring outerName, TableKind outerTableKind,
179 cstring outerKeyType, unsigned outerSize) const override;
180 void emitMain(Util::SourceCodeBuilder *builder, cstring functionName,
181 cstring argName) const override;
182 void emitPreamble(Util::SourceCodeBuilder *builder) const override;
183 void emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format, int argc = 0,
184 ...) const override;
185 cstring dataOffset(cstring base) const override {
186 return cstring("((void*)(long)") + base + "->data)";
187 }
188 cstring dataEnd(cstring base) const override {
189 return cstring("((void*)(long)") + base + "->data_end)";
190 }
191 cstring dataLength(cstring base) const override { return cstring(base) + "->len"; }
192 cstring forwardReturnCode() const override { return "TC_ACT_OK"_cs; }
193 cstring dropReturnCode() const override { return "TC_ACT_SHOT"_cs; }
194 cstring abortReturnCode() const override { return "TC_ACT_SHOT"_cs; }
195 cstring sysMapPath() const override { return "/sys/fs/bpf/tc/globals"_cs; }
196
197 cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; }
198
199 void annotateTableWithBTF(Util::SourceCodeBuilder *builder, cstring name, cstring keyType,
200 cstring valueType) const;
201};
202
204 public:
205 explicit P4TCTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "P4TC"_cs) {}
206 // FIXME: The code is terrible broken: the function is called on both
207 // *parsed* and *unparsed* annotations (!!!!)
208 static cstring getByteOrderFromAnnotation(const IR::IAnnotated *node) {
209 if (const auto *anno = node->getAnnotation("tc_type"_cs)) {
210 cstring value = anno->needsParsing()
211 ? anno->getUnparsed().at(0)->text
212 : anno->getExpr().at(0)->checkedTo<IR::StringLiteral>()->value;
213 if (value == "macaddr" || value == "ipv4" || value == "ipv6" || value == "be16" ||
214 value == "be32" || value == "be64") {
215 return "NETWORK"_cs;
216 }
217 }
218 return "HOST"_cs;
219 }
220
221 cstring getByteOrder(P4::TypeMap *typeMap, const IR::P4Action *action,
222 const IR::Expression *exp) const {
223 if (auto mem = exp->to<IR::Member>()) {
224 auto type = typeMap->getType(mem->expr, true);
225 if (type->is<IR::Type_StructLike>()) {
226 auto field = type->to<IR::Type_StructLike>()->getField(mem->member);
227 return getByteOrderFromAnnotation(field);
228 }
229 } else if (action) {
230 auto paramList = action->getParameters();
231 if (paramList != nullptr && !paramList->empty()) {
232 for (auto param : paramList->parameters) {
233 if (param->name.originalName == exp->toString()) {
234 return getByteOrderFromAnnotation(param);
235 }
236 }
237 }
238 }
239 return "HOST"_cs;
240 }
241};
242
245 public:
246 explicit XdpTarget(bool emitTrace) : KernelSamplesTarget(emitTrace, "XDP"_cs) {}
247
248 cstring forwardReturnCode() const override { return "XDP_PASS"_cs; }
249 cstring dropReturnCode() const override { return "XDP_DROP"_cs; }
250 cstring abortReturnCode() const override { return "XDP_ABORTED"_cs; }
251 cstring redirectReturnCode() const { return "XDP_REDIRECT"_cs; }
252 cstring sysMapPath() const override { return "/sys/fs/bpf/xdp/globals"_cs; }
253 cstring packetDescriptorType() const override { return "struct xdp_md"_cs; }
254
255 cstring dataLength(cstring base) const override {
256 return cstring("(") + base + "->data_end - " + base + "->data)";
257 }
258 void emitResizeBuffer(Util::SourceCodeBuilder *builder, cstring buffer,
259 cstring offsetVar) const override;
260 void emitMain(Util::SourceCodeBuilder *builder, cstring functionName,
261 cstring argName) const override {
262 builder->appendFormat("int %v(%v *%v)", functionName, packetDescriptorType(), argName);
263 }
264};
265
267class BccTarget : public Target {
268 public:
269 BccTarget() : Target("BCC"_cs) {}
270 void emitLicense(Util::SourceCodeBuilder *, cstring) const override {}
271 void emitCodeSection(Util::SourceCodeBuilder *, cstring) const override {}
272 void emitIncludes(Util::SourceCodeBuilder *builder) const override;
273 void emitResizeBuffer(Util::SourceCodeBuilder *, cstring, cstring) const override {}
274 void emitTableLookup(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
275 cstring value) const override;
276 void emitTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
277 cstring value) const override;
278 void emitUserTableUpdate(Util::SourceCodeBuilder *builder, cstring tblName, cstring key,
279 cstring value) const override;
280 void emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName, TableKind tableKind,
281 cstring keyType, cstring valueType, unsigned size) const override;
282 void emitMain(Util::SourceCodeBuilder *builder, cstring functionName,
283 cstring argName) const override;
284 cstring dataOffset(cstring base) const override { return base; }
285 cstring dataEnd(cstring base) const override {
286 return cstring("(") + base + " + " + base + "->len)";
287 }
288 cstring dataLength(cstring base) const override { return cstring(base) + "->len"; }
289 cstring forwardReturnCode() const override { return "0"_cs; }
290 cstring dropReturnCode() const override { return "1"_cs; }
291 cstring abortReturnCode() const override { return "1"_cs; }
292 cstring sysMapPath() const override { return "/sys/fs/bpf"_cs; }
293 cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; }
294};
295
299 public:
300 TestTarget() : KernelSamplesTarget(false, "Userspace Test"_cs) {}
301
302 void emitResizeBuffer(Util::SourceCodeBuilder *, cstring, cstring) const override {}
303 void emitIncludes(Util::SourceCodeBuilder *builder) const override;
304 void emitTableDecl(Util::SourceCodeBuilder *builder, cstring tblName, TableKind tableKind,
305 cstring keyType, cstring valueType, unsigned size) const override;
306 cstring dataOffset(cstring base) const override {
307 return cstring("((void*)(long)") + base + "->data)";
308 }
309 cstring dataEnd(cstring base) const override {
310 return cstring("((void*)(long)(") + base + "->data + " + base + "->len))";
311 }
312 cstring forwardReturnCode() const override { return "true"_cs; }
313 cstring dropReturnCode() const override { return "false"_cs; }
314 cstring abortReturnCode() const override { return "false"_cs; }
315 cstring sysMapPath() const override { return "/sys/fs/bpf"_cs; }
316 cstring packetDescriptorType() const override { return "struct __sk_buff"_cs; }
317};
318
319} // namespace P4::EBPF
320
321#endif /* BACKENDS_EBPF_TARGET_H_ */
Represents a target compiled by bcc that uses the TC.
Definition ebpf/target.h:267
Definition ebpf/target.h:130
void emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format, int argc=0,...) const override
Definition ebpf/target.cpp:179
void emitMapInMapDecl(Util::SourceCodeBuilder *builder, cstring innerName, TableKind innerTableKind, cstring innerKeyType, cstring innerValueType, unsigned innerSize, cstring outerName, TableKind outerTableKind, cstring outerKeyType, unsigned outerSize) const override
Definition ebpf/target.cpp:114
Definition ebpf/target.h:203
Definition ebpf/target.h:44
virtual void emitTraceMessage(Util::SourceCodeBuilder *builder, const char *format, int argc,...) const
Definition ebpf/target.cpp:25
virtual void emitMapInMapDecl(Util::SourceCodeBuilder *builder, cstring innerName, TableKind innerTableKind, cstring innerKeyType, cstring innerValueType, unsigned innerSize, cstring outerName, TableKind outerTableKind, cstring outerKeyType, unsigned outerSize) const
Definition ebpf/target.h:81
Definition ebpf/target.h:298
Target XDP.
Definition ebpf/target.h:244
Definition typeMap.h:41
Definition sourceCodeBuilder.h:29
Definition cstring.h:85
Definition codeGen.cpp:25
Definition cstring.h:80
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51