P4C
The P4 Compiler
Loading...
Searching...
No Matches
ebpfCodeGen.h
1/*
2Copyright (C) 2023 Intel Corporation
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
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing,
11software distributed 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
14and limitations under the License.
15*/
16
17#ifndef BACKENDS_TC_EBPFCODEGEN_H_
18#define BACKENDS_TC_EBPFCODEGEN_H_
19
20// FIXME: these include each other and present file
21#include "backend.h"
22#include "tcExterns.h"
23
24namespace P4::TC {
25
26using namespace P4::literals;
27
29class EBPFPnaParser;
30class EBPFRegisterPNA;
31
32// Similar to class PSAEbpfGenerator in backends/ebpf/psa/ebpfPsaGen.h
33
34class PNAEbpfGenerator : public EBPF::EbpfCodeGenerator {
35 public:
36 EBPF::EBPFPipeline *pipeline;
37 const ConvertToBackendIR *tcIR;
38
39 PNAEbpfGenerator(const EbpfOptions &options, std::vector<EBPF::EBPFType *> &ebpfTypes,
40 EBPF::EBPFPipeline *pipeline, const ConvertToBackendIR *tcIR)
41 : EBPF::EbpfCodeGenerator(options, ebpfTypes), pipeline(pipeline), tcIR(tcIR) {}
42
43 virtual void emit(EBPF::CodeBuilder *builder) const = 0;
44 virtual void emitInstances(EBPF::CodeBuilder *builder) const = 0;
45 virtual void emitParser(EBPF::CodeBuilder *builder) const = 0;
46 virtual void emitHeader(EBPF::CodeBuilder *builder) const = 0;
47 void emitPNAIncludes(EBPF::CodeBuilder *builder) const;
48 void emitPreamble(EBPF::CodeBuilder *builder) const override;
49 void emitCommonPreamble(EBPF::CodeBuilder *builder) const override;
50 void emitInternalStructures(EBPF::CodeBuilder *pBuilder) const override;
51 void emitTypes(EBPF::CodeBuilder *builder) const override;
52 void emitGlobalHeadersMetadata(EBPF::CodeBuilder *builder) const override;
53 void emitPipelineInstances(EBPF::CodeBuilder *builder) const override;
54 void emitP4TCFilterFields(EBPF::CodeBuilder *builder) const;
55 void emitP4TCActionParam(EBPF::CodeBuilder *builder) const;
56 cstring getProgramName() const;
57};
58
59// Similar to class PSAErrorCodesGen in backends/ebpf/psa/ebpfPsaGen.cpp
60
61class PNAErrorCodesGen : public Inspector {
62 EBPF::CodeBuilder *builder;
63
64 public:
65 explicit PNAErrorCodesGen(EBPF::CodeBuilder *builder) : builder(builder) {}
66
67 bool preorder(const IR::Type_Error *errors) override {
68 int id = -1;
69 for (auto decl : errors->members) {
70 ++id;
71 if (decl->srcInfo.isValid()) {
72 auto sourceFile = decl->srcInfo.getSourceFile();
73 // all the error codes are located in core.p4 file, they are defined in pna.h
74 if (sourceFile.endsWith("p4include/core.p4")) continue;
75 }
76
77 builder->emitIndent();
78 builder->appendFormat("static const ParserError_t %s = %d", decl->name.name, id);
79 builder->endOfStatement(true);
80
81 // type ParserError_t is u8, which can have values from 0 to 255
82 if (id > 255) {
83 ::P4::error(ErrorType::ERR_OVERLIMIT,
84 "%1%: Reached maximum number of possible errors", decl);
85 }
86 }
87 builder->newline();
88 return false;
89 }
90};
91
92// Similar to class PSAArchTC in backends/ebpf/psa/ebpfPsaGen.h
93
94class PNAArchTC : public PNAEbpfGenerator {
95 public:
97
98 PNAArchTC(const EbpfOptions &options, std::vector<EBPF::EBPFType *> &ebpfTypes,
100 const ConvertToBackendIR *tcIR)
101 : PNAEbpfGenerator(options, ebpfTypes, pipeline, tcIR), xdp(xdp) {}
102
103 void emit(EBPF::CodeBuilder *builder) const override;
104 void emitParser(EBPF::CodeBuilder *builder) const override;
105 void emitHeader(EBPF::CodeBuilder *builder) const override;
106 void emitInstances(EBPF::CodeBuilder *builder) const override;
107};
108
109class TCIngressPipelinePNA : public EBPF::TCIngressPipeline {
110 public:
111 TCIngressPipelinePNA(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
112 P4::TypeMap *typeMap)
113 : EBPF::TCIngressPipeline(name, options, refMap, typeMap) {}
114
115 void emit(EBPF::CodeBuilder *builder) override;
116 void emitLocalVariables(EBPF::CodeBuilder *builder) override;
117 void emitGlobalMetadataInitializer(EBPF::CodeBuilder *builder) override;
118 void emitTrafficManager(EBPF::CodeBuilder *builder) override;
119
120 DECLARE_TYPEINFO(TCIngressPipelinePNA, EBPF::TCIngressPipeline);
121};
122
123class PnaStateTranslationVisitor : public EBPF::PsaStateTranslationVisitor {
124 public:
125 explicit PnaStateTranslationVisitor(P4::ReferenceMap *refMap, P4::TypeMap *typeMap,
127 : EBPF::PsaStateTranslationVisitor(refMap, typeMap, prsr) {}
128
129 protected:
130 void compileExtractField(const IR::Expression *expr, const IR::StructField *field,
131 unsigned hdrOffsetBits, EBPF::EBPFType *type) override;
132 void compileLookahead(const IR::Expression *destination) override;
133};
134
135class EBPFPnaParser : public EBPF::EBPFPsaParser {
136 public:
137 EBPFPnaParser(const EBPF::EBPFProgram *program, const IR::ParserBlock *block,
138 const P4::TypeMap *typeMap);
139 void emit(EBPF::CodeBuilder *builder) override;
140 void emitRejectState(EBPF::CodeBuilder *) override;
141 void emitDeclaration(EBPF::CodeBuilder *builder, const IR::Declaration *decl) override;
142
143 DECLARE_TYPEINFO(EBPFPnaParser, EBPF::EBPFPsaParser);
144};
145
146class EBPFTablePNA : public EBPF::EBPFTablePSA {
147 protected:
148 EBPF::ActionTranslationVisitor *createActionTranslationVisitor(cstring valueName,
149 const EBPF::EBPFProgram *program,
150 const IR::P4Action *action,
151 bool isDefaultAction) const;
152 void validateKeys() const override;
153 void initDirectCounters();
154 const ConvertToBackendIR *tcIR;
155
156 public:
157 EBPFTablePNA(const EBPF::EBPFProgram *program, const IR::TableBlock *table,
158 EBPF::CodeGenInspector *codeGen, const ConvertToBackendIR *tcIR)
159 : EBPF::EBPFTablePSA(program, table, codeGen), tcIR(tcIR) {
160 initDirectCounters();
161 }
162 void emitInitializer(EBPF::CodeBuilder *builder) override;
163 void emitDefaultActionStruct(EBPF::CodeBuilder *builder);
164 void emitKeyType(EBPF::CodeBuilder *builder) override;
165 void emitValueType(EBPF::CodeBuilder *builder) override;
166 void emitValueStructStructure(EBPF::CodeBuilder *builder) override;
167 void emitActionArguments(EBPF::CodeBuilder *builder, const IR::P4Action *action, cstring name);
168 void emitKeyPNA(EBPF::CodeBuilder *builder, cstring keyName);
169 bool isMatchTypeSupported(const IR::Declaration_ID *matchType) override {
170 if (matchType->name.name == "range" || matchType->name.name == "rangelist" ||
171 matchType->name.name == "optional")
172 return 1;
173 return EBPF::EBPFTable::isMatchTypeSupported(matchType);
174 }
175 void emitAction(EBPF::CodeBuilder *builder, cstring valueName,
176 cstring actionRunVariable) override;
177 void emitValueActionIDNames(EBPF::CodeBuilder *builder) override;
178 cstring p4ActionToActionIDName(const IR::P4Action *action) const;
179
180 DECLARE_TYPEINFO(EBPFTablePNA, EBPF::EBPFTablePSA);
181};
182
183class IngressDeparserPNA : public EBPF::EBPFDeparserPSA {
184 public:
185 IngressDeparserPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control,
186 const IR::Parameter *parserHeaders, const IR::Parameter *istd)
187 : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd) {}
188
189 bool addExternDeclaration = false;
190 bool build() override;
191 void emit(EBPF::CodeBuilder *builder) override;
192 void emitPreDeparser(EBPF::CodeBuilder *builder) override;
193 void emitDeclaration(EBPF::CodeBuilder *builder, const IR::Declaration *decl) override;
194
195 void emitExternDefinition(EBPF::CodeBuilder *builder) {
196 if (addExternDeclaration) {
197 builder->emitIndent();
198 builder->appendLine("struct p4tc_ext_bpf_params ext_params = {};");
199 }
200 }
201 DECLARE_TYPEINFO(IngressDeparserPNA, EBPF::EBPFDeparserPSA);
202};
203
204// Similar to class ConvertToEbpfPSA in backends/ebpf/psa/ebpfPsaGen.h
205
206class ConvertToEbpfPNA : public Transform {
207 const EbpfOptions &options;
208 P4::TypeMap *typemap;
209 P4::ReferenceMap *refmap;
210 const PNAEbpfGenerator *ebpf_program;
211 const ConvertToBackendIR *tcIR;
212
213 public:
214 ConvertToEbpfPNA(const EbpfOptions &options, P4::ReferenceMap *refmap, P4::TypeMap *typemap,
215 const ConvertToBackendIR *tcIR)
216 : options(options), typemap(typemap), refmap(refmap), ebpf_program(nullptr), tcIR(tcIR) {}
217
218 const PNAEbpfGenerator *build(const IR::ToplevelBlock *prog);
219 const IR::Node *preorder(IR::ToplevelBlock *p) override;
220 const PNAEbpfGenerator *getEBPFProgram() { return ebpf_program; }
221};
222
223// Similar to class ConvertToEbpfPipeline in backends/ebpf/psa/ebpfPsaGen.h
224
225class ConvertToEbpfPipelineTC : public Inspector {
226 const cstring name;
227 const EBPF::pipeline_type type;
228 const EbpfOptions &options;
229 const IR::ParserBlock *parserBlock;
230 const IR::ControlBlock *controlBlock;
231 const IR::ControlBlock *deparserBlock;
232 P4::TypeMap *typemap;
233 P4::ReferenceMap *refmap;
234 EBPF::EBPFPipeline *pipeline;
235 const ConvertToBackendIR *tcIR;
236
237 public:
238 ConvertToEbpfPipelineTC(cstring name, EBPF::pipeline_type type, const EbpfOptions &options,
239 const IR::ParserBlock *parserBlock,
240 const IR::ControlBlock *controlBlock,
241 const IR::ControlBlock *deparserBlock, P4::ReferenceMap *refmap,
242 P4::TypeMap *typemap, const ConvertToBackendIR *tcIR)
243 : name(name),
244 type(type),
245 options(options),
246 parserBlock(parserBlock),
247 controlBlock(controlBlock),
248 deparserBlock(deparserBlock),
249 typemap(typemap),
250 refmap(refmap),
251 pipeline(nullptr),
252 tcIR(tcIR) {}
253
254 bool preorder(const IR::PackageBlock *block) override;
255 EBPF::EBPFPipeline *getEbpfPipeline() { return pipeline; }
256};
257
258// Similar to class ConvertToEBPFParserPSA in backends/ebpf/psa/ebpfPsaGen.h
259
260class ConvertToEBPFParserPNA : public Inspector {
261 EBPF::EBPFProgram *program;
262 P4::TypeMap *typemap;
263 TC::EBPFPnaParser *parser;
264
265 public:
266 ConvertToEBPFParserPNA(EBPF::EBPFProgram *program, P4::TypeMap *typemap)
267 : program(program), typemap(typemap), parser(nullptr) {}
268
269 bool preorder(const IR::ParserBlock *prsr) override;
270 bool preorder(const IR::P4ValueSet *pvs) override;
271 EBPF::EBPFParser *getEBPFParser() { return parser; }
272};
273
274class EBPFControlPNA : public EBPF::EBPFControlPSA {
275 public:
276 bool addExternDeclaration = false;
277 std::map<cstring, EBPFRegisterPNA *> pna_registers;
278
279 EBPFControlPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control,
280 const IR::Parameter *parserHeaders)
281 : EBPF::EBPFControlPSA(program, control, parserHeaders) {}
282
283 EBPFRegisterPNA *getRegister(cstring name) const {
284 auto result = ::P4::get(pna_registers, name);
285 BUG_CHECK(result != nullptr, "No register named %1%", name);
286 return result;
287 }
288 void emitExternDefinition(EBPF::CodeBuilder *builder) {
289 if (addExternDeclaration) {
290 builder->emitIndent();
291 builder->appendLine("struct p4tc_ext_bpf_params ext_params = {};");
292 builder->emitIndent();
293 builder->appendLine("struct p4tc_ext_bpf_val ext_val = {};");
294 builder->emitIndent();
295 builder->appendLine("struct p4tc_ext_bpf_val *ext_val_ptr;");
296 }
297 }
298};
299
300// Similar to class ConvertToEBPFControlPSA in backends/ebpf/psa/ebpfPsaGen.h
301
302class ConvertToEBPFControlPNA : public Inspector {
303 EBPF::EBPFProgram *program;
304 EBPF::pipeline_type type;
305 EBPFControlPNA *control;
306
307 const IR::Parameter *parserHeaders;
308 P4::ReferenceMap *refmap;
309
310 const ConvertToBackendIR *tcIR;
311
312 public:
313 ConvertToEBPFControlPNA(EBPF::EBPFProgram *program, const IR::Parameter *parserHeaders,
314 P4::ReferenceMap *refmap, EBPF::pipeline_type type,
315 const ConvertToBackendIR *tcIR)
316 : program(program),
317 type(type),
318 control(nullptr),
319 parserHeaders(parserHeaders),
320 refmap(refmap),
321 tcIR(tcIR) {}
322
323 bool preorder(const IR::TableBlock *) override;
324 bool preorder(const IR::ControlBlock *) override;
325 bool preorder(const IR::Declaration_Variable *) override;
326 bool preorder(const IR::Member *m) override;
327 bool preorder(const IR::IfStatement *a) override;
328 bool preorder(const IR::ExternBlock *instance) override;
329 bool checkPnaTimestampMem(const IR::Member *m);
330 EBPFControlPNA *getEBPFControl() { return control; }
331};
332
333// Similar to class ConvertToEBPFDeparserPSA in backends/ebpf/psa/ebpfPsaGen.h
334
335class ConvertToEBPFDeparserPNA : public Inspector {
336 EBPF::EBPFProgram *program;
337 const IR::Parameter *parserHeaders;
338 const IR::Parameter *istd;
339 const ConvertToBackendIR *tcIR;
340 TC::IngressDeparserPNA *deparser;
341
342 public:
343 ConvertToEBPFDeparserPNA(EBPF::EBPFProgram *program, const IR::Parameter *parserHeaders,
344 const IR::Parameter *istd, const ConvertToBackendIR *tcIR)
345 : program(program),
346 parserHeaders(parserHeaders),
347 istd(istd),
348 tcIR(tcIR),
349 deparser(nullptr) {}
350
351 bool preorder(const IR::ControlBlock *) override;
352 bool preorder(const IR::Declaration_Instance *) override;
353 EBPF::EBPFDeparserPSA *getEBPFDeparser() { return deparser; }
354};
355
356// Similar to class ControlBodyTranslatorPSA in backends/ebpf/psa/ebpfPsaControl.h
357
358class ControlBodyTranslatorPNA : public EBPF::ControlBodyTranslator {
359 public:
360 const ConvertToBackendIR *tcIR;
361 const EBPF::EBPFTablePSA *table;
362 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control);
363 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control,
364 const ConvertToBackendIR *tcIR);
365 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control, const ConvertToBackendIR *tcIR,
366 const EBPF::EBPFTablePSA *table);
367 void processFunction(const P4::ExternFunction *function) override;
368 void processApply(const P4::ApplyMethod *method) override;
369 bool checkPnaPortMem(const IR::Member *m);
370 virtual cstring getParamName(const IR::PathExpression *);
371 bool preorder(const IR::AssignmentStatement *a) override;
372 void processMethod(const P4::ExternMethod *method) override;
373 bool preorder(const IR::Member *) override;
374 bool IsTableAddOnMiss(const IR::P4Table *table);
375 const IR::P4Action *GetAddOnMissHitAction(cstring actionName);
376 void ValidateAddOnMissMissAction(const IR::P4Action *act);
377};
378
379// Similar to class ActionTranslationVisitorPSA in backends/ebpf/psa/ebpfPsaControl.h
380
381class ActionTranslationVisitorPNA : public EBPF::ActionTranslationVisitor,
382 public ControlBodyTranslatorPNA {
383 protected:
384 const EBPF::EBPFTablePSA *table;
385 bool isDefaultAction;
386
387 public:
388 const ConvertToBackendIR *tcIR;
389 ActionTranslationVisitorPNA(const EBPF::EBPFProgram *program, cstring valueName,
390 const EBPF::EBPFTablePSA *table, const ConvertToBackendIR *tcIR,
391 const IR::P4Action *act, bool isDefaultAction);
392 bool preorder(const IR::PathExpression *pe) override;
393 bool isActionParameter(const IR::Expression *expression) const;
394 void processMethod(const P4::ExternMethod *method) override;
395
396 cstring getParamInstanceName(const IR::Expression *expression) const override;
397 cstring getParamName(const IR::PathExpression *) override;
398};
399
400// Similar to class DeparserHdrEmitTranslator in backends/ebpf/ebpfDeparser.h
401
402class DeparserHdrEmitTranslatorPNA : public EBPF::DeparserPrepareBufferTranslator {
403 protected:
404 const EBPF::EBPFDeparser *deparser;
405
406 public:
407 explicit DeparserHdrEmitTranslatorPNA(const EBPF::EBPFDeparser *deparser);
408
409 void processMethod(const P4::ExternMethod *method) override;
410 void emitField(EBPF::CodeBuilder *builder, cstring field, const IR::Expression *hdrExpr,
411 unsigned alignment, EBPF::EBPFType *type, bool isMAC);
412};
413
414class CRCChecksumAlgorithmPNA : public EBPF::CRCChecksumAlgorithm {
415 public:
416 CRCChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name, int width)
417 : EBPF::CRCChecksumAlgorithm(program, name, width) {}
418
419 static void emitUpdateMethod(EBPF::CodeBuilder *builder, int crcWidth);
420};
421
422class CRC16ChecksumAlgorithmPNA : public CRCChecksumAlgorithmPNA {
423 public:
424 CRC16ChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name)
425 : CRCChecksumAlgorithmPNA(program, name, 16) {
426 initialValue = "0"_cs;
427 // We use a 0x8005 polynomial.
428 // 0xA001 comes from 0x8005 value bits reflection.
429 polynomial = "0xA001"_cs;
430 updateMethod = "crc16_update"_cs;
431 finalizeMethod = "crc16_finalize"_cs;
432 }
433
434 static void emitGlobals(EBPF::CodeBuilder *builder);
435};
436
437class CRC32ChecksumAlgorithmPNA : public CRCChecksumAlgorithmPNA {
438 public:
439 CRC32ChecksumAlgorithmPNA(const EBPF::EBPFProgram *program, cstring name)
440 : CRCChecksumAlgorithmPNA(program, name, 32) {
441 initialValue = "0xffffffff"_cs;
442 // We use a 0x04C11DB7 polynomial.
443 // 0xEDB88320 comes from 0x04C11DB7 value bits reflection.
444 polynomial = "0xEDB88320"_cs;
445 updateMethod = "crc32_update"_cs;
446 finalizeMethod = "crc32_finalize"_cs;
447 }
448
449 static void emitGlobals(EBPF::CodeBuilder *builder);
450};
451
453 public:
454 static EBPFHashAlgorithmTypeFactoryPNA *instance() {
455 static EBPFHashAlgorithmTypeFactoryPNA factory;
456 return &factory;
457 }
458
459 void emitGlobals(EBPF::CodeBuilder *builder) {
460 CRC16ChecksumAlgorithmPNA::emitGlobals(builder);
461 CRC32ChecksumAlgorithmPNA::emitGlobals(builder);
462 }
463
464 EBPF::EBPFHashAlgorithmPSA *create(int type, const EBPF::EBPFProgram *program, cstring name);
465};
466
467} // namespace P4::TC
468
469#endif /* BACKENDS_TC_EBPFCODEGEN_H_ */
Definition methodInstance.h:129
Definition ebpfTable.h:26
Definition ebpfPsaHashAlgorithm.h:74
Definition ebpf/codeGen.h:33
Definition ebpf/codeGen.h:41
Definition ebpfControl.h:28
This translator emits buffer preparation (eg. which headers will be emitted)
Definition ebpfDeparser.h:38
Definition ebpfPsaControl.h:58
Definition ebpfDeparser.h:63
Definition ebpfPsaDeparser.h:39
Definition ebpfPsaHashAlgorithm.h:26
Definition ebpfPsaHashAlgorithm.h:172
Definition ebpfParser.h:79
EBPFPipeline represents a single eBPF program in the TC/XDP hook.
Definition ebpfPipeline.h:28
cstring name
A custom name of eBPF program.
Definition ebpfPipeline.h:31
Definition ebpfProgram.h:39
Definition ebpfPsaParser.h:40
Definition ebpfPsaTable.h:29
Base class for EBPF types.
Definition ebpfType.h:29
Definition ebpfPsaGen.h:31
Definition ebpfPsaParser.h:29
Definition ebpfPipeline.h:199
Definition xdpHelpProgram.h:24
Definition ebpfOptions.h:26
Definition methodInstance.h:181
Definition methodInstance.h:149
Definition node.h:95
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition tc/backend.h:49
Definition ebpfCodeGen.h:274
Definition ebpfCodeGen.h:452
Definition ebpfCodeGen.h:135
Definition tcExterns.h:53
void validateKeys() const override
Definition ebpfCodeGen.cpp:2099
Definition ebpfCodeGen.h:183
void emitPreDeparser(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:1175
void emit(EBPF::CodeBuilder *builder) const override
Definition ebpfCodeGen.cpp:169
void emitParser(EBPF::CodeBuilder *builder) const override
Definition ebpfCodeGen.cpp:215
Definition ebpfCodeGen.h:34
void emitLocalVariables(EBPF::CodeBuilder *builder) override
Generates a set of helper variables that are used during packet processing.
Definition ebpfCodeGen.cpp:515
void emitGlobalMetadataInitializer(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:443
void emitTrafficManager(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:484
Definition typeMap.h:41
Definition cstring.h:85
This file defines functions for the pass to generate the introspection file.
Definition tc/backend.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition error.h:51