P4C
The P4 Compiler
Loading...
Searching...
No Matches
ebpfPipeline.h
1/*
2 * SPDX-FileCopyrightText: 2022 Open Networking Foundation
3 * SPDX-FileCopyrightText: 2022 Orange
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7#ifndef BACKENDS_EBPF_PSA_EBPFPIPELINE_H_
8#define BACKENDS_EBPF_PSA_EBPFPIPELINE_H_
9
10#include "backends/ebpf/ebpfProgram.h"
11#include "backends/ebpf/target.h"
12#include "ebpfPsaControl.h"
13#include "ebpfPsaDeparser.h"
14
15namespace P4::EBPF {
16
18class EBPFPipeline : public EBPFProgram {
19 public:
33 cstring packetPathVar, pktInstanceVar;
39 unsigned packetMark;
42
43 EBPFControlPSA *control;
44 EBPFDeparserPSA *deparser;
45
46 EBPFPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
47 P4::TypeMap *typeMap)
48 : EBPFProgram(options, nullptr, refMap, typeMap, nullptr),
49 name(name),
50 packetMark(0x99),
51 control(nullptr),
52 deparser(nullptr) {
53 sectionName = "classifier/" + name;
54 functionName = name.replace('-', '_') + "_func";
55 errorEnum = "ParserError_t"_cs;
56 packetStartVar = "pkt"_cs;
57 headerStartVar = "hdr_start"_cs;
58 contextVar = "skb"_cs;
59 lengthVar = "pkt_len"_cs;
60 endLabel = "deparser"_cs;
61 timestampVar = "tstamp"_cs;
62 ifindexVar = "skb->ifindex"_cs;
63 compilerGlobalMetadata = "compiler_meta__"_cs;
64 packetPathVar = compilerGlobalMetadata + "->packet_path"_cs;
65 pktInstanceVar = compilerGlobalMetadata + "->instance"_cs;
66 priorityVar = "skb->priority"_cs;
67 oneKey = EBPFModel::reserved("one"_cs);
68 inputPortVar = "ebpf_input_port"_cs;
69 progTarget = new KernelSamplesTarget(options.emitTraceMessages);
70 }
71
74 bool isEmpty() const;
75
76 virtual cstring dropReturnCode() {
77 if (sectionName.startsWith("xdp")) {
78 return "XDP_DROP"_cs;
79 }
80
81 // TC is the default hookpoint
82 return "TC_ACT_SHOT"_cs;
83 }
84 virtual cstring forwardReturnCode() {
85 if (sectionName.startsWith("xdp")) {
86 return "XDP_PASS"_cs;
87 }
88
89 // TC is the default hookpoint
90 return "TC_ACT_OK"_cs;
91 }
92
93 virtual void emit(CodeBuilder *builder) = 0;
94 virtual void emitTrafficManager(CodeBuilder *builder) = 0;
95 virtual void emitPSAControlInputMetadata(CodeBuilder *builder) = 0;
96 virtual void emitPSAControlOutputMetadata(CodeBuilder *builder) = 0;
97
99 void emitLocalHeaderInstancesAsPointers(CodeBuilder *builder);
101 void emitCPUMAPHeadersInitializers(CodeBuilder *builder);
104 void emitHeaderInstances(CodeBuilder *builder) override;
106 void emitLocalVariables(CodeBuilder *builder) override;
107
110 void emitUserMetadataInstance(CodeBuilder *builder);
111
112 virtual void emitCPUMAPInitializers(CodeBuilder *builder);
113 virtual void emitCPUMAPLookup(CodeBuilder *builder);
116 virtual void emitGlobalMetadataInitializer(CodeBuilder *builder);
117
118 virtual void emitPacketLength(CodeBuilder *builder);
119 virtual void emitTimestamp(CodeBuilder *builder);
120 void emitInputPortMapping(CodeBuilder *builder);
121
122 void emitHeadersFromCPUMAP(CodeBuilder *builder);
123 void emitMetadataFromCPUMAP(CodeBuilder *builder);
124
125 bool hasAnyMeter() const {
126 auto directMeter = std::find_if(control->tables.begin(), control->tables.end(),
127 [](std::pair<const cstring, EBPFTable *> elem) {
128 return !elem.second->to<EBPFTablePSA>()->meters.empty();
129 });
130 bool anyDirectMeter = directMeter != control->tables.end();
131 return anyDirectMeter || (!control->meters.empty());
132 }
138 bool shouldEmitTimestamp() const { return hasAnyMeter() || control->timestampIsUsed; }
139
140 DECLARE_TYPEINFO(EBPFPipeline, EBPFProgram);
141};
142
145class EBPFIngressPipeline : public EBPFPipeline {
146 public:
147 unsigned int maxResubmitDepth;
151
152 EBPFIngressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
153 P4::TypeMap *typeMap)
154 : EBPFPipeline(name, options, refMap, typeMap) {
155 // FIXME: hardcoded
156 maxResubmitDepth = 4;
157 // actUnspecCode should not collide with TC/XDP return codes,
158 // but it's safe to use the same value as TC_ACT_UNSPEC.
159 actUnspecCode = -1;
160 }
161
162 void emitSharedMetadataInitializer(CodeBuilder *builder);
163
164 void emit(CodeBuilder *builder) override;
165 void emitPSAControlInputMetadata(CodeBuilder *builder) override;
166 void emitPSAControlOutputMetadata(CodeBuilder *builder) override;
167
168 DECLARE_TYPEINFO(EBPFIngressPipeline, EBPFPipeline);
169};
170
173class EBPFEgressPipeline : public EBPFPipeline {
174 public:
175 EBPFEgressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
176 P4::TypeMap *typeMap)
177 : EBPFPipeline(name, options, refMap, typeMap) {}
178
179 void emit(CodeBuilder *builder) override;
180 void emitPSAControlInputMetadata(CodeBuilder *builder) override;
181 void emitPSAControlOutputMetadata(CodeBuilder *builder) override;
182 void emitCPUMAPLookup(CodeBuilder *builder) override;
183
184 virtual void emitCheckPacketMarkMetadata(CodeBuilder *builder) = 0;
185
186 DECLARE_TYPEINFO(EBPFEgressPipeline, EBPFPipeline);
187};
188
189class TCIngressPipeline : public EBPFIngressPipeline {
190 public:
191 TCIngressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
192 P4::TypeMap *typeMap)
193 : EBPFIngressPipeline(name, options, refMap, typeMap) {}
194
195 void emitGlobalMetadataInitializer(CodeBuilder *builder) override;
196 void emitTrafficManager(CodeBuilder *builder) override;
197
198 private:
199 void emitTCWorkaroundUsingMeta(CodeBuilder *builder);
200 void emitTCWorkaroundUsingHead(CodeBuilder *builder);
201 void emitTCWorkaroundUsingCPUMAP(CodeBuilder *builder);
202
203 DECLARE_TYPEINFO(TCIngressPipeline, EBPFIngressPipeline);
204};
205
206class TCEgressPipeline : public EBPFEgressPipeline {
207 public:
208 TCEgressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
209 P4::TypeMap *typeMap)
210 : EBPFEgressPipeline(name, options, refMap, typeMap) {}
211
212 void emitTrafficManager(CodeBuilder *builder) override;
213 void emitCheckPacketMarkMetadata(CodeBuilder *builder) override;
214
215 DECLARE_TYPEINFO(TCEgressPipeline, EBPFEgressPipeline);
216};
217
218class XDPIngressPipeline : public EBPFIngressPipeline {
219 public:
220 XDPIngressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
221 P4::TypeMap *typeMap)
222 : EBPFIngressPipeline(name, options, refMap, typeMap) {
223 sectionName = "xdp_ingress/" + name;
224 ifindexVar = "skb->ingress_ifindex"_cs;
225 packetPathVar = compilerGlobalMetadata + "->packet_path"_cs;
226 progTarget = new XdpTarget(options.emitTraceMessages);
227 }
228
229 void emitGlobalMetadataInitializer(CodeBuilder *builder) override;
230 void emitTrafficManager(CodeBuilder *builder) override;
231
232 DECLARE_TYPEINFO(XDPIngressPipeline, EBPFIngressPipeline);
233};
234
235class XDPEgressPipeline : public EBPFEgressPipeline {
236 public:
237 XDPEgressPipeline(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
238 P4::TypeMap *typeMap)
239 : EBPFEgressPipeline(name, options, refMap, typeMap) {
240 sectionName = "xdp_devmap/" + name;
241 ifindexVar = "skb->egress_ifindex"_cs;
242 // we do not support packet path, instance & priority in the XDP egress.
243 packetPathVar = "0"_cs;
244 pktInstanceVar = "0"_cs;
245 priorityVar = "0"_cs;
246 progTarget = new XdpTarget(options.emitTraceMessages);
247 }
248
249 void emitGlobalMetadataInitializer(CodeBuilder *builder) override;
250 void emitTrafficManager(CodeBuilder *builder) override;
251 void emitCheckPacketMarkMetadata(CodeBuilder *builder) override;
252
253 DECLARE_TYPEINFO(XDPEgressPipeline, EBPFEgressPipeline);
254};
255
256class TCTrafficManagerForXDP : public TCIngressPipeline {
257 public:
258 TCTrafficManagerForXDP(cstring name, const EbpfOptions &options, P4::ReferenceMap *refMap,
259 P4::TypeMap *typeMap)
260 : TCIngressPipeline(name, options, refMap, typeMap) {}
261
262 void emitGlobalMetadataInitializer(CodeBuilder *builder) override;
263 void emit(CodeBuilder *builder) override;
264
265 private:
266 void emitReadXDP2TCMetadataFromHead(CodeBuilder *builder);
267 void emitReadXDP2TCMetadataFromCPUMAP(CodeBuilder *builder);
268
269 DECLARE_TYPEINFO(TCTrafficManagerForXDP, TCIngressPipeline);
270};
271
272} // namespace P4::EBPF
273
274#endif /* BACKENDS_EBPF_PSA_EBPFPIPELINE_H_ */
Definition ebpf/codeGen.h:33
Definition ebpfPsaControl.h:49
Definition ebpfPsaDeparser.h:29
Definition ebpfPipeline.h:145
int actUnspecCode
Definition ebpfPipeline.h:150
EBPFPipeline represents a single eBPF program in the TC/XDP hook.
Definition ebpfPipeline.h:18
void emitLocalHeaderInstancesAsPointers(CodeBuilder *builder)
Generates a pointer to struct Headers_t and puts it on the BPF program's stack.
Definition ebpfPipeline.cpp:93
cstring name
A custom name of eBPF program.
Definition ebpfPipeline.h:21
void emitHeaderInstances(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:105
cstring packetPathVar
Variables storing global metadata (packet_path & instance).
Definition ebpfPipeline.h:33
cstring inputPortVar
A variable to store ifindex after mapping (e.g. due to recirculation).
Definition ebpfPipeline.h:41
bool shouldEmitTimestamp() const
Definition ebpfPipeline.h:138
cstring ifindexVar
Variable storing ingress interface index.
Definition ebpfPipeline.h:29
cstring oneKey
A variable name storing "1" value. Used to access BPF array map index.
Definition ebpfPipeline.h:37
virtual void emitGlobalMetadataInitializer(CodeBuilder *builder)
Definition ebpfPipeline.cpp:141
void emitLocalVariables(CodeBuilder *builder) override
Generates a set of helper variables that are used during packet processing.
Definition ebpfPipeline.cpp:38
bool isEmpty() const
Definition ebpfPipeline.cpp:11
unsigned packetMark
A unique mark used to differentiate packets processed by P4/eBPF from others.
Definition ebpfPipeline.h:39
void emitCPUMAPHeadersInitializers(CodeBuilder *builder)
Generates a pointer to struct hdr_md. The pointer is used to access data from per-CPU map.
Definition ebpfPipeline.cpp:100
cstring sectionName
eBPF section name, which should a concatenation of classifier/ + a custom name.
Definition ebpfPipeline.h:23
cstring compilerGlobalMetadata
A name of an internal variable storing global metadata.
Definition ebpfPipeline.h:35
cstring timestampVar
Variable name storing current timestamp retrieved from bpf_ktime_get_ns().
Definition ebpfPipeline.h:27
cstring priorityVar
Variable storing skb->priority value (TC only).
Definition ebpfPipeline.h:31
void emitUserMetadataInstance(CodeBuilder *builder)
Definition ebpfPipeline.cpp:82
cstring contextVar
Variable name storing pointer to eBPF packet descriptor (e.g., __sk_buff).
Definition ebpfPipeline.h:25
Definition ebpfProgram.h:30
EBPFProgram(const EbpfOptions &options, const IR::P4Program *program, P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::ToplevelBlock *toplevel)
return 'true' on success
Definition ebpfProgram.h:56
Definition ebpf/target.h:130
void emitTrafficManager(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:544
void emitGlobalMetadataInitializer(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:460
void emitGlobalMetadataInitializer(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:738
void emitGlobalMetadataInitializer(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:694
void emitGlobalMetadataInitializer(CodeBuilder *builder) override
Definition ebpfPipeline.cpp:670
Target XDP.
Definition ebpf/target.h:249
Definition ebpfOptions.h:26
Class used to encode maps from paths to declarations.
Definition referenceMap.h:67
Definition typeMap.h:32
Definition cstring.h:85
Definition codeGen.cpp:25