P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
bfruntime_arch_handler.h
1/* Copyright 2021 Intel Corporation
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14*/
15#ifndef DPDK_CONTROL_PLANE_BFRUNTIME_ARCH_HANDLER_H_
16#define DPDK_CONTROL_PLANE_BFRUNTIME_ARCH_HANDLER_H_
17
18#include <iostream>
19#include <optional>
20#include <set>
21#include <unordered_map>
22#include <vector>
23
24#pragma GCC diagnostic push
25#pragma GCC diagnostic ignored "-Wunused-parameter"
26#pragma GCC diagnostic ignored "-Wpedantic"
27#include "backends/dpdk/p4/config/p4info.pb.h"
28#pragma GCC diagnostic pop
29
30#include "control-plane/bfruntime.h"
31#include "control-plane/p4RuntimeArchHandler.h"
32#include "control-plane/p4RuntimeArchStandard.h"
33#include "control-plane/p4RuntimeSerializer.h"
34#include "control-plane/typeSpecConverter.h"
35#include "frontends/common/resolveReferences/referenceMap.h"
36#include "frontends/p4/externInstance.h"
37#include "frontends/p4/methodInstance.h"
38#include "frontends/p4/typeMap.h"
39#include "midend/eliminateTypedefs.h"
40
42using P4::TypeMap;
45
46namespace p4configv1 = ::p4::config::v1;
47
48namespace P4 {
49
53namespace ControlPlaneAPI {
54
56namespace Standard {
57
58cstring prefix(cstring p, cstring str) { return p.isNullOrEmpty() ? str : p + "." + str; }
59
61class SymbolTypeDPDK final : public SymbolType {
62 public:
63 SymbolTypeDPDK() = delete;
64
65 static P4RuntimeSymbolType P4RT_ACTION_SELECTOR() {
66 return P4RuntimeSymbolType::make(dpdk::P4Ids::ACTION_SELECTOR);
67 }
68};
69
73 const cstring name; // The fully qualified external name of this action selector.
74 const int64_t size; // TODO(hanw): size does not make sense with new ActionSelector P4 extern
75 const int64_t maxGroupSize;
76 const int64_t numGroups;
77 const IR::IAnnotated *annotations; // If non-null, any annotations applied to this action
78 // profile declaration.
79
80 static constexpr int64_t defaultMaxGroupSize = 120;
81
82 p4rt_id_t getId(const P4RuntimeSymbolTableIface &symbols) const {
83 return symbols.getId(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), name + "_sel");
84 }
85};
86
87template <Arch arch>
89 protected:
90 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
91
92 public:
93 template <typename Func>
94 void forAllPipeBlocks(const IR::ToplevelBlock *evaluatedProgram, Func function) {
95 auto main = evaluatedProgram->getMain();
96 if (!main) ::error(ErrorType::ERR_NOT_FOUND, "Program does not contain a `main` module");
97 auto cparams = main->getConstructorParameters();
98 int index = -1;
99 for (auto param : main->constantValue) {
100 index++;
101 if (!param.second) continue;
102 auto pipe = param.second;
103 if (!pipe->is<IR::PackageBlock>()) continue;
104 auto idxParam = cparams->getParameter(index);
105 auto pipeName = idxParam->name;
106 function(pipeName, pipe->to<IR::PackageBlock>());
107 }
108 }
109
114
115 using Counter = p4configv1::Counter;
116 using Meter = p4configv1::Meter;
117 using CounterSpec = p4configv1::CounterSpec;
118 using MeterSpec = p4configv1::MeterSpec;
119
120 BFRuntimeArchHandler(ReferenceMap *refMap, TypeMap *typeMap,
121 const IR::ToplevelBlock *evaluatedProgram)
122 : P4RuntimeArchHandlerCommon<arch>(refMap, typeMap, evaluatedProgram) {
123 // Create a map of all blocks to their pipe names. This map will
124 // be used during collect and post processing to prefix
125 // table/extern instances wherever applicable with a fully qualified
126 // name. This distinction is necessary when the driver looks up
127 // context.json across multiple pipes for the table name
128 forAllPipeBlocks(evaluatedProgram, [&](cstring pipeName, const IR::PackageBlock *pkg) {
129 Helpers::forAllEvaluatedBlocks(pkg, [&](const IR::Block *block) {
130 auto decl = pkg->node->to<IR::Declaration_Instance>();
131 cstring blockNamePrefix = pipeName;
132 if (decl) blockNamePrefix = decl->controlPlaneName();
133 blockNamePrefixMap[block] = blockNamePrefix;
134 });
135 });
136 }
137
138 cstring getBlockNamePrefix(const IR::Block *blk) {
139 if (blockNamePrefixMap.count(blk) > 0) return blockNamePrefixMap[blk];
140 return "pipe";
141 }
142
143 static p4configv1::Extern *getP4InfoExtern(P4RuntimeSymbolType typeId, cstring typeName,
144 p4configv1::P4Info *p4info) {
145 for (auto &externType : *p4info->mutable_externs()) {
146 if (externType.extern_type_id() == static_cast<p4rt_id_t>(typeId)) return &externType;
147 }
148 auto *externType = p4info->add_externs();
149 externType->set_extern_type_id(static_cast<p4rt_id_t>(typeId));
150 externType->set_extern_type_name(typeName);
151 return externType;
152 }
153
154 static void addP4InfoExternInstance(const P4RuntimeSymbolTableIface &symbols,
155 P4RuntimeSymbolType typeId, cstring typeName, cstring name,
156 const IR::IAnnotated *annotations,
157 const ::google::protobuf::Message &message,
158 p4configv1::P4Info *p4info, cstring pipeName = "") {
159 auto *externType = getP4InfoExtern(typeId, typeName, p4info);
160 auto *externInstance = externType->add_instances();
161 auto *pre = externInstance->mutable_preamble();
162 pre->set_id(symbols.getId(typeId, name));
163 pre->set_name(prefix(pipeName, name));
164 pre->set_alias(symbols.getAlias(name));
165 Helpers::addAnnotations(pre, annotations);
166 Helpers::addDocumentation(pre, annotations);
167 externInstance->mutable_info()->PackFrom(message);
168 }
169
170 std::optional<ActionSelector> getActionSelector(const IR::ExternBlock *instance) {
171 auto actionSelDecl = instance->node->to<IR::IDeclaration>();
172 // to be deleted, used to support deprecated ActionSelector constructor.
173 auto size = instance->getParameterValue("size");
174 BUG_CHECK(size->is<IR::Constant>(), "Non-constant size");
175 return ActionSelector{actionSelDecl->controlPlaneName(), size->to<IR::Constant>()->asInt(),
176 ActionSelector::defaultMaxGroupSize,
177 size->to<IR::Constant>()->asInt(),
178 actionSelDecl->to<IR::IAnnotated>()};
179 }
180
181 void addActionSelector(const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4Info,
182 const ActionSelector &actionSelector, cstring pipeName = "") {
183 ::dpdk::ActionSelector selector;
184 selector.set_max_group_size(actionSelector.maxGroupSize);
185 selector.set_num_groups(actionSelector.numGroups);
186 p4configv1::ActionProfile profile;
187 profile.set_size(actionSelector.size);
188 auto tablesIt = this->actionProfilesRefs.find(actionSelector.name);
189 if (tablesIt != this->actionProfilesRefs.end()) {
190 for (const auto &table : tablesIt->second) {
191 profile.add_table_ids(symbols.getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
192 selector.add_table_ids(symbols.getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
193 }
194 }
195 // We use the ActionSelector name for the action profile, and add a "_sel" suffix for
196 // the action selector.
197 cstring profileName = actionSelector.name;
198 selector.set_action_profile_id(
199 symbols.getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
200 cstring selectorName = profileName + "_sel";
201 addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), "ActionSelector",
202 selectorName, actionSelector.annotations, selector, p4Info,
203 pipeName);
204 }
205
207 const IR::ExternBlock *externBlock) override {
209
210 auto decl = externBlock->node->to<IR::IDeclaration>();
211 if (decl == nullptr) return;
212 if (externBlock->type->name == "Digest") {
213 symbols->add(SymbolType::P4RT_DIGEST(), decl);
214 } else if (externBlock->type->name == ActionSelectorTraits<arch>::typeName()) {
215 auto selName = decl->controlPlaneName() + "_sel";
216 auto profName = decl->controlPlaneName();
217 symbols->add(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), selName);
218 symbols->add(SymbolType::P4RT_ACTION_PROFILE(), profName);
219 }
220 }
221
222 void addTableProperties(const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
223 p4configv1::Table *table, const IR::TableBlock *tableBlock) override {
224 P4RuntimeArchHandlerCommon<arch>::addTableProperties(symbols, p4info, table, tableBlock);
225
226 auto tableDeclaration = tableBlock->container;
227 bool supportsTimeout = getSupportsTimeout(tableDeclaration);
228 if (supportsTimeout) {
229 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
230 } else {
231 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
232 }
233
234 // add pipe name prefix to the table names
235 auto pipeName = getBlockNamePrefix(tableBlock);
236 auto *pre = table->mutable_preamble();
237 if (pre->name() == tableDeclaration->controlPlaneName())
238 pre->set_name(prefix(pipeName, pre->name()));
239 }
240
241 void addExternInstance(const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
242 const IR::ExternBlock *externBlock) override {
243 P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
244
245 auto decl = externBlock->node->to<IR::Declaration_Instance>();
246 if (decl == nullptr) return;
247
248 // DPDK control plane software requires pipe name to be prefixed to the
249 // table and extern names
250 cstring pipeName = getBlockNamePrefix(externBlock);
251
252 auto p4RtTypeInfo = p4info->mutable_type_info();
253 if (externBlock->type->name == "Digest") {
254 auto digest = getDigest(decl, p4RtTypeInfo);
255 if (digest) this->addDigest(symbols, p4info, *digest);
256 } else if (externBlock->type->name == "ActionSelector") {
257 auto actionSelector = getActionSelector(externBlock);
258 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
259 for (auto &extType : *p4info->mutable_action_profiles()) {
260 auto *pre = extType.mutable_preamble();
261 if (pre->name() == decl->controlPlaneName()) {
262 pre->set_name(prefix(pipeName, pre->name()));
263 break;
264 }
265 }
266 } else if (externBlock->type->name == "ActionProfile") {
267 for (auto &extType : *p4info->mutable_action_profiles()) {
268 auto *pre = extType.mutable_preamble();
269 if (pre->name() == decl->controlPlaneName()) {
270 pre->set_name(prefix(pipeName, pre->name()));
271 break;
272 }
273 }
274 } else if (externBlock->type->name == "Meter") {
275 for (auto &extType : *p4info->mutable_meters()) {
276 auto *pre = extType.mutable_preamble();
277 if (pre->name() == decl->controlPlaneName()) {
278 pre->set_name(prefix(pipeName, pre->name()));
279 break;
280 }
281 }
282 } else if (externBlock->type->name == "Counter") {
283 for (auto &extType : *p4info->mutable_counters()) {
284 auto *pre = extType.mutable_preamble();
285 if (pre->name() == decl->controlPlaneName()) {
286 pre->set_name(prefix(pipeName, pre->name()));
287 break;
288 }
289 }
290 } else if (externBlock->type->name == "Register") {
291 for (auto &extType : *p4info->mutable_registers()) {
292 auto *pre = extType.mutable_preamble();
293 if (pre->name() == decl->controlPlaneName()) {
294 pre->set_name(prefix(pipeName, pre->name()));
295 break;
296 }
297 }
298 }
299 }
300
302 std::optional<Digest> getDigest(const IR::Declaration_Instance *decl,
303 p4configv1::P4TypeInfo *p4RtTypeInfo) {
304 BUG_CHECK(decl->type->is<IR::Type_Specialized>(), "%1%: expected Type_Specialized",
305 decl->type);
306 auto type = decl->type->to<IR::Type_Specialized>();
307 BUG_CHECK(type->arguments->size() == 1, "%1%: expected one type argument", decl);
308 auto typeArg = type->arguments->at(0);
309 auto typeSpec =
310 TypeSpecConverter::convert(this->refMap, this->typeMap, typeArg, p4RtTypeInfo);
311 BUG_CHECK(typeSpec != nullptr,
312 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
313
314 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
315 }
316
319 static bool getSupportsTimeout(const IR::P4Table *table) {
320 auto timeout = table->properties->getProperty("psa_idle_timeout");
321
322 if (timeout == nullptr) return false;
323
324 if (auto exprValue = timeout->value->to<IR::ExpressionValue>()) {
325 if (auto expr = exprValue->expression) {
326 if (auto member = expr->to<IR::Member>()) {
327 if (member->member == "NOTIFY_CONTROL") {
328 return true;
329 } else if (member->member == "NO_TIMEOUT") {
330 return false;
331 }
332 } else if (expr->is<IR::PathExpression>()) {
333 ::error(ErrorType::ERR_UNEXPECTED,
334 "Unresolved value %1% for psa_idle_timeout "
335 "property on table %2%. Must be a constant and one of "
336 "{ NOTIFY_CONTROL, NO_TIMEOUT }",
337 timeout, table);
338 return false;
339 }
340 }
341 }
342
343 ::error(ErrorType::ERR_UNEXPECTED,
344 "Unexpected value %1% for psa_idle_timeout "
345 "property on table %2%. Supported values are "
346 "{ NOTIFY_CONTROL, NO_TIMEOUT }",
347 timeout, table);
348 return false;
349 }
350};
351
352class BFRuntimeArchHandlerPSA final : public BFRuntimeArchHandler<Arch::PSA> {
353 public:
355 const IR::ToplevelBlock *evaluatedProgram)
356 : BFRuntimeArchHandler(refMap, typeMap, evaluatedProgram) {}
357};
358
359class BFRuntimeArchHandlerPNA final : public BFRuntimeArchHandler<Arch::PNA> {
360 public:
362 const IR::ToplevelBlock *evaluatedProgram)
363 : BFRuntimeArchHandler(refMap, typeMap, evaluatedProgram) {}
364};
365
369 ReferenceMap *refMap, TypeMap *typeMap,
370 const IR::ToplevelBlock *evaluatedProgram) const override {
372 evaluatedProgram);
373 }
374};
375
379 ReferenceMap *refMap, TypeMap *typeMap,
380 const IR::ToplevelBlock *evaluatedProgram) const override {
382 evaluatedProgram);
383 }
384};
385
386} // namespace Standard
387
388} // namespace ControlPlaneAPI
389
390 /* end group control_plane */
391} // namespace P4
392
393#endif /* DPDK_CONTROL_PLANE_BFRUNTIME_ARCH_HANDLER_H_ */
Definition p4RuntimeArchHandler.h:136
Definition p4RuntimeArchHandler.h:106
virtual p4rt_id_t getId(P4RuntimeSymbolType type, const IR::IDeclaration *declaration) const =0
virtual cstring getAlias(cstring name) const =0
virtual void add(P4RuntimeSymbolType type, const IR::IDeclaration *declaration)=0
Add a @type symbol, extracting the name and id from @declaration.
Definition p4RuntimeArchHandler.h:60
Definition bfruntime_arch_handler.h:88
std::optional< Digest > getDigest(const IR::Declaration_Instance *decl, p4configv1::P4TypeInfo *p4RtTypeInfo)
Definition bfruntime_arch_handler.h:302
static bool getSupportsTimeout(const IR::P4Table *table)
Definition bfruntime_arch_handler.h:319
void collectExternInstance(P4RuntimeSymbolTableIface *symbols, const IR::ExternBlock *externBlock) override
Collects architecture-specific @externBlock instance in @symbols table.
Definition bfruntime_arch_handler.h:206
Definition bfruntime_arch_handler.h:359
Definition bfruntime_arch_handler.h:352
Definition p4RuntimeArchStandard.h:523
void collectExternInstance(P4RuntimeSymbolTableIface *symbols, const IR::ExternBlock *externBlock) override
Collects architecture-specific @externBlock instance in @symbols table.
Definition p4RuntimeArchStandard.h:593
Extends P4RuntimeSymbolType for the DPDK extern types.
Definition bfruntime_arch_handler.h:61
Definition p4RuntimeArchStandard.h:277
static const ::p4::config::v1::P4DataTypeSpec * convert(const P4::ReferenceMap *refMap, P4::TypeMap *typeMap, const IR::Type *type, ::p4::config::v1::P4TypeInfo *typeInfo)
Definition typeSpecConverter.cpp:386
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
Definition typeMap.h:42
Definition cstring.h:72
void forAllEvaluatedBlocks(const IR::Block *block, Func function)
Definition p4RuntimeArchHandler.h:231
std::optional< ExternInstance > getExternInstanceFromProperty(const IR::P4Table *table, const cstring &propertyName, ReferenceMap *refMap, TypeMap *typeMap, bool *isConstructedInPlace)
Definition p4RuntimeArchHandler.cpp:41
bool isExternPropertyConstructedInPlace(const IR::P4Table *table, const cstring &propertyName)
Definition p4RuntimeArchHandler.cpp:77
void addDocumentation(Message *message, const IR::IAnnotated *annotated)
' and '@description' annotations if present.
Definition p4RuntimeArchHandler.h:304
A traits class describing the properties of "counterlike" things.
Definition p4RuntimeArchHandler.h:365
Definition p4RuntimeArchStandard.h:348
Definition p4RuntimeArchStandard.h:50
Definition p4RuntimeArchStandard.h:423
Definition p4RuntimeArchStandard.h:52
Definition applyOptionsPragmas.cpp:24
Definition p4RuntimeArchHandler.h:201
Definition bfruntime_arch_handler.h:72
The architecture handler builder implementation for PNA.
Definition bfruntime_arch_handler.h:377
P4::ControlPlaneAPI::P4RuntimeArchHandlerIface * operator()(ReferenceMap *refMap, TypeMap *typeMap, const IR::ToplevelBlock *evaluatedProgram) const override
Definition bfruntime_arch_handler.h:378
The architecture handler builder implementation for PSA.
Definition bfruntime_arch_handler.h:367
P4::ControlPlaneAPI::P4RuntimeArchHandlerIface * operator()(ReferenceMap *refMap, TypeMap *typeMap, const IR::ToplevelBlock *evaluatedProgram) const override
Definition bfruntime_arch_handler.h:368