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