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