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};
109
110class TCIngressPipelinePNA : public EBPF::TCIngressPipeline {
111 public:
112 TCIngressPipelinePNA(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
113 P4::TypeMap *typeMap)
114 : EBPF::TCIngressPipeline(name, options, refMap, typeMap) {}
115
116 void emit(EBPF::CodeBuilder *builder) override;
117 void emitLocalVariables(EBPF::CodeBuilder *builder) override;
118 void emitGlobalMetadataInitializer(EBPF::CodeBuilder *builder) override;
119 void emitTrafficManager(EBPF::CodeBuilder *builder) override;
120
121 DECLARE_TYPEINFO(TCIngressPipelinePNA, EBPF::TCIngressPipeline);
122};
123
124class PnaStateTranslationVisitor : public EBPF::PsaStateTranslationVisitor {
125 public:
126 explicit PnaStateTranslationVisitor(P4::ReferenceMap *refMap, P4::TypeMap *typeMap,
128 : EBPF::PsaStateTranslationVisitor(refMap, typeMap, prsr) {}
129
130 bool preorder(const IR::Member *expression) override;
131
132 protected:
133 void compileExtractField(const IR::Expression *expr, const IR::StructField *field,
134 unsigned hdrOffsetBits, EBPF::EBPFType *type) override;
135 void compileLookahead(const IR::Expression *destination) override;
136};
137
138class EBPFPnaParser : public EBPF::EBPFPsaParser {
139 public:
140 EBPFPnaParser(const EBPF::EBPFProgram *program, const IR::ParserBlock *block,
141 const P4::TypeMap *typeMap);
142 void emit(EBPF::CodeBuilder *builder) override;
143 void emitRejectState(EBPF::CodeBuilder *) override;
144 void emitDeclaration(EBPF::CodeBuilder *builder, const IR::Declaration *decl) override;
145
146 DECLARE_TYPEINFO(EBPFPnaParser, EBPF::EBPFPsaParser);
147};
148
149class EBPFTablePNA : public EBPF::EBPFTablePSA {
150 protected:
151 EBPF::ActionTranslationVisitor *createActionTranslationVisitor(cstring valueName,
152 const EBPF::EBPFProgram *program,
153 const IR::P4Action *action,
154 bool isDefaultAction) const;
155 void validateKeys() const override;
156 void initDirectCounters();
157 void initDirectMeters();
158 const ConvertToBackendIR *tcIR;
159
160 public:
161 EBPFTablePNA(const EBPF::EBPFProgram *program, const IR::TableBlock *table,
162 EBPF::CodeGenInspector *codeGen, const ConvertToBackendIR *tcIR)
163 : EBPF::EBPFTablePSA(program, table, codeGen), tcIR(tcIR) {
164 initDirectCounters();
165 initDirectMeters();
166 }
167 void emitInitializer(EBPF::CodeBuilder *builder) override;
168 void emitDefaultActionStruct(EBPF::CodeBuilder *builder);
169 void emitKeyType(EBPF::CodeBuilder *builder) override;
170 void emitValueType(EBPF::CodeBuilder *builder) override;
171 void emitValueStructStructure(EBPF::CodeBuilder *builder) override;
172 void emitActionArguments(EBPF::CodeBuilder *builder, const IR::P4Action *action, cstring name);
173 void emitKeyPNA(EBPF::CodeBuilder *builder, cstring keyName);
174 bool isMatchTypeSupported(const IR::Declaration_ID *matchType) override {
175 if (matchType->name.name == "range" || matchType->name.name == "rangelist" ||
176 matchType->name.name == "optional")
177 return 1;
178 return EBPF::EBPFTable::isMatchTypeSupported(matchType);
179 }
180 void emitAction(EBPF::CodeBuilder *builder, cstring valueName,
181 cstring actionRunVariable) override;
182 void emitValueActionIDNames(EBPF::CodeBuilder *builder) override;
183 cstring p4ActionToActionIDName(const IR::P4Action *action) const;
184
185 DECLARE_TYPEINFO(EBPFTablePNA, EBPF::EBPFTablePSA);
186};
187
189
190class DeparserBodyTranslatorPNA : public EBPF::DeparserBodyTranslatorPSA {
191 public:
192 explicit DeparserBodyTranslatorPNA(const IngressDeparserPNA *deparser);
193
194 void processFunction(const P4::ExternFunction *function) override;
195};
196
197class IngressDeparserPNA : public EBPF::EBPFDeparserPSA {
198 public:
199 mutable bool touched_skb_metadata;
200
201 IngressDeparserPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control,
202 const IR::Parameter *parserHeaders, const IR::Parameter *istd)
203 : EBPF::EBPFDeparserPSA(program, control, parserHeaders, istd),
204 touched_skb_metadata(false) {
205 codeGen = new DeparserBodyTranslatorPNA(this);
206 }
207
208 bool addExternDeclaration = false;
209 bool build() override;
210 void emit(EBPF::CodeBuilder *builder) override;
211 void emitPreDeparser(EBPF::CodeBuilder *builder) override;
212 void emitDeclaration(EBPF::CodeBuilder *builder, const IR::Declaration *decl) override;
213
214 void emitExternDefinition(EBPF::CodeBuilder *builder) {
215 if (addExternDeclaration) {
216 builder->emitIndent();
217 builder->appendLine("struct p4tc_ext_bpf_params ext_params = {};");
218 }
219 }
220 DECLARE_TYPEINFO(IngressDeparserPNA, EBPF::EBPFDeparserPSA);
221};
222
223// Similar to class ConvertToEbpfPSA in backends/ebpf/psa/ebpfPsaGen.h
224
225class ConvertToEbpfPNA : public Transform {
226 const EbpfOptions &options;
227 P4::TypeMap *typemap;
228 P4::ReferenceMap *refmap;
229 const PNAEbpfGenerator *ebpf_program;
230 const ConvertToBackendIR *tcIR;
231
232 public:
233 ConvertToEbpfPNA(const EbpfOptions &options, P4::ReferenceMap *refmap, P4::TypeMap *typemap,
234 const ConvertToBackendIR *tcIR)
235 : options(options), typemap(typemap), refmap(refmap), ebpf_program(nullptr), tcIR(tcIR) {}
236
237 const PNAEbpfGenerator *build(const IR::ToplevelBlock *prog);
238 const IR::Node *preorder(IR::ToplevelBlock *p) override;
239 const PNAEbpfGenerator *getEBPFProgram() { return ebpf_program; }
240};
241
242// Similar to class ConvertToEbpfPipeline in backends/ebpf/psa/ebpfPsaGen.h
243
244class ConvertToEbpfPipelineTC : public Inspector {
245 const cstring name;
246 const EBPF::pipeline_type type;
247 const EbpfOptions &options;
248 const IR::ParserBlock *parserBlock;
249 const IR::ControlBlock *controlBlock;
250 const IR::ControlBlock *deparserBlock;
251 P4::TypeMap *typemap;
252 P4::ReferenceMap *refmap;
253 EBPF::EBPFPipeline *pipeline;
254 const ConvertToBackendIR *tcIR;
255
256 public:
257 ConvertToEbpfPipelineTC(cstring name, EBPF::pipeline_type type, const EbpfOptions &options,
258 const IR::ParserBlock *parserBlock,
259 const IR::ControlBlock *controlBlock,
260 const IR::ControlBlock *deparserBlock, P4::ReferenceMap *refmap,
261 P4::TypeMap *typemap, const ConvertToBackendIR *tcIR)
262 : name(name),
263 type(type),
264 options(options),
265 parserBlock(parserBlock),
266 controlBlock(controlBlock),
267 deparserBlock(deparserBlock),
268 typemap(typemap),
269 refmap(refmap),
270 pipeline(nullptr),
271 tcIR(tcIR) {}
272
273 bool preorder(const IR::PackageBlock *block) override;
274 EBPF::EBPFPipeline *getEbpfPipeline() { return pipeline; }
275};
276
277// Similar to class ConvertToEBPFParserPSA in backends/ebpf/psa/ebpfPsaGen.h
278
279class ConvertToEBPFParserPNA : public Inspector {
280 EBPF::EBPFProgram *program;
281 P4::TypeMap *typemap;
282 TC::EBPFPnaParser *parser;
283
284 public:
285 ConvertToEBPFParserPNA(EBPF::EBPFProgram *program, P4::TypeMap *typemap)
286 : program(program), typemap(typemap), parser(nullptr) {}
287
288 bool preorder(const IR::ParserBlock *prsr) override;
289 bool preorder(const IR::P4ValueSet *pvs) override;
290 EBPF::EBPFParser *getEBPFParser() { return parser; }
291};
292
293class EBPFControlPNA : public EBPF::EBPFControlPSA {
294 public:
295 bool addExternDeclaration = false;
296 std::map<cstring, EBPFRegisterPNA *> pna_registers;
297 std::map<cstring, EBPFHashPNA *> pna_hashes;
298
299 mutable bool touched_skb_metadata;
300
301 EBPFControlPNA(const EBPF::EBPFProgram *program, const IR::ControlBlock *control,
302 const IR::Parameter *parserHeaders)
303 : EBPF::EBPFControlPSA(program, control, parserHeaders), touched_skb_metadata(false) {}
304
305 EBPFRegisterPNA *getRegister(cstring name) const {
306 auto result = ::P4::get(pna_registers, name);
307 BUG_CHECK(result != nullptr, "No register named %1%", name);
308 return result;
309 }
310 EBPFHashPNA *getHash(cstring name) const {
311 auto result = ::P4::get(pna_hashes, name);
312 return result;
313 }
314 void emitExternDefinition(EBPF::CodeBuilder *builder) {
315 if (addExternDeclaration) {
316 builder->emitIndent();
317 builder->appendLine("struct p4tc_ext_bpf_params ext_params = {};");
318 builder->emitIndent();
319 builder->appendLine("struct p4tc_ext_bpf_val ext_val = {};");
320 builder->emitIndent();
321 builder->appendLine("struct p4tc_ext_bpf_val *ext_val_ptr;");
322 }
323 }
324 void emitTableTypes(EBPF::CodeBuilder *builder) { EBPF::EBPFControl::emitTableTypes(builder); }
325 void emit(EBPF::CodeBuilder *builder);
326};
327
328// Similar to class ConvertToEBPFControlPSA in backends/ebpf/psa/ebpfPsaGen.h
329
330class ConvertToEBPFControlPNA : public Inspector {
331 EBPF::EBPFProgram *program;
332 EBPF::pipeline_type type;
333 EBPFControlPNA *control;
334
335 const IR::Parameter *parserHeaders;
336 P4::ReferenceMap *refmap;
337
338 const ConvertToBackendIR *tcIR;
339
340 public:
341 ConvertToEBPFControlPNA(EBPF::EBPFProgram *program, const IR::Parameter *parserHeaders,
342 P4::ReferenceMap *refmap, EBPF::pipeline_type type,
343 const ConvertToBackendIR *tcIR)
344 : program(program),
345 type(type),
346 control(nullptr),
347 parserHeaders(parserHeaders),
348 refmap(refmap),
349 tcIR(tcIR) {}
350
351 bool preorder(const IR::TableBlock *) override;
352 bool preorder(const IR::ControlBlock *) override;
353 bool preorder(const IR::Declaration_Variable *) override;
354 bool preorder(const IR::Member *m) override;
355 bool preorder(const IR::IfStatement *a) override;
356 bool preorder(const IR::ExternBlock *instance) override;
357 bool checkPnaTimestampMem(const IR::Member *m);
358 EBPFControlPNA *getEBPFControl() { return control; }
359};
360
361// Similar to class ConvertToEBPFDeparserPSA in backends/ebpf/psa/ebpfPsaGen.h
362
363class ConvertToEBPFDeparserPNA : public Inspector {
364 EBPF::EBPFProgram *program;
365 const IR::Parameter *parserHeaders;
366 const IR::Parameter *istd;
367 const ConvertToBackendIR *tcIR;
368 TC::IngressDeparserPNA *deparser;
369
370 public:
371 ConvertToEBPFDeparserPNA(EBPF::EBPFProgram *program, const IR::Parameter *parserHeaders,
372 const IR::Parameter *istd, const ConvertToBackendIR *tcIR)
373 : program(program),
374 parserHeaders(parserHeaders),
375 istd(istd),
376 tcIR(tcIR),
377 deparser(nullptr) {}
378
379 bool preorder(const IR::ControlBlock *) override;
380 bool preorder(const IR::Declaration_Instance *) override;
381 EBPF::EBPFDeparserPSA *getEBPFDeparser() { return deparser; }
382};
383
384// Similar to class ControlBodyTranslatorPSA in backends/ebpf/psa/ebpfPsaControl.h
385
386class ControlBodyTranslatorPNA : public EBPF::ControlBodyTranslator {
387 public:
388 const ConvertToBackendIR *tcIR;
389 const EBPF::EBPFTablePSA *table;
390 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control);
391 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control,
392 const ConvertToBackendIR *tcIR);
393 explicit ControlBodyTranslatorPNA(const EBPFControlPNA *control, const ConvertToBackendIR *tcIR,
394 const EBPF::EBPFTablePSA *table);
395 void processFunction(const P4::ExternFunction *function) override;
396 void processApply(const P4::ApplyMethod *method) override;
397 virtual cstring getParamName(const IR::PathExpression *);
398 bool preorder(const IR::AssignmentStatement *a) override;
399 void processMethod(const P4::ExternMethod *method) override;
400 bool preorder(const IR::Member *) override;
401 bool IsTableAddOnMiss(const IR::P4Table *table);
402 const IR::P4Action *GetAddOnMissHitAction(cstring actionName);
403 void ValidateAddOnMissMissAction(const IR::P4Action *act);
404};
405
406// Similar to class ActionTranslationVisitorPSA in backends/ebpf/psa/ebpfPsaControl.h
407
408class ActionTranslationVisitorPNA : public EBPF::ActionTranslationVisitor,
409 public ControlBodyTranslatorPNA {
410 protected:
411 const EBPF::EBPFTablePSA *table;
412 bool isDefaultAction;
413
414 public:
415 const ConvertToBackendIR *tcIR;
416 ActionTranslationVisitorPNA(const EBPF::EBPFProgram *program, cstring valueName,
417 const EBPF::EBPFTablePSA *table, const ConvertToBackendIR *tcIR,
418 const IR::P4Action *act, bool isDefaultAction);
419 bool preorder(const IR::PathExpression *pe) override;
420 bool isActionParameter(const IR::Expression *expression) const;
421 void processMethod(const P4::ExternMethod *method) override;
422
423 cstring getParamInstanceName(const IR::Expression *expression) const override;
424 cstring getParamName(const IR::PathExpression *) override;
425};
426
427// Similar to class DeparserHdrEmitTranslator in backends/ebpf/ebpfDeparser.h
428
429class DeparserHdrEmitTranslatorPNA : public EBPF::DeparserPrepareBufferTranslator {
430 protected:
431 const EBPF::EBPFDeparser *deparser;
432
433 public:
434 explicit DeparserHdrEmitTranslatorPNA(const EBPF::EBPFDeparser *deparser);
435
436 void processMethod(const P4::ExternMethod *method) override;
437 void emitField(EBPF::CodeBuilder *builder, cstring field, const IR::Expression *hdrExpr,
438 unsigned alignment, EBPF::EBPFType *type, bool isMAC);
439};
440
442 public:
443 static EBPFHashAlgorithmTypeFactoryPNA *instance() {
444 static EBPFHashAlgorithmTypeFactoryPNA factory;
445 return &factory;
446 }
447
448 EBPF::EBPFHashAlgorithmPSA *create(int type, const EBPF::EBPFProgram *program, cstring name);
449};
450
451} // namespace P4::TC
452
453#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: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:194
Definition methodInstance.h:168
Definition node.h:94
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition tc/backend.h:49
Definition ebpfCodeGen.h:190
Definition ebpfCodeGen.h:293
Definition ebpfCodeGen.h:441
Definition tcExterns.h:180
Definition ebpfCodeGen.h:138
Definition tcExterns.h:53
void validateKeys() const override
Definition ebpfCodeGen.cpp:2354
Definition ebpfCodeGen.h:197
void emitPreDeparser(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:1212
void emit(EBPF::CodeBuilder *builder) const override
Definition ebpfCodeGen.cpp:179
void emitParser(EBPF::CodeBuilder *builder) const override
Definition ebpfCodeGen.cpp:225
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:547
void emitGlobalMetadataInitializer(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:474
void emitTrafficManager(EBPF::CodeBuilder *builder) override
Definition ebpfCodeGen.cpp:516
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