89 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
92 template <
typename Func>
93 void forAllPipeBlocks(
const IR::ToplevelBlock *evaluatedProgram, Func function) {
94 auto main = evaluatedProgram->getMain();
95 if (!main) ::error(ErrorType::ERR_NOT_FOUND,
"Program does not contain a `main` module");
96 auto cparams = main->getConstructorParameters();
98 for (
auto param : main->constantValue) {
100 if (!param.second)
continue;
101 auto pipe = param.second;
102 if (!pipe->is<IR::PackageBlock>())
continue;
103 auto idxParam = cparams->getParameter(index);
104 auto pipeName = idxParam->name;
105 function(pipeName, pipe->to<IR::PackageBlock>());
114 using Counter = p4configv1::Counter;
115 using Meter = p4configv1::Meter;
116 using CounterSpec = p4configv1::CounterSpec;
117 using MeterSpec = p4configv1::MeterSpec;
120 const IR::ToplevelBlock *evaluatedProgram)
127 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
129 auto decl = pkg->node->to<IR::Declaration_Instance>();
130 cstring blockNamePrefix = pipeName;
131 if (decl) blockNamePrefix = decl->controlPlaneName();
132 blockNamePrefixMap[block] = blockNamePrefix;
137 cstring getBlockNamePrefix(
const IR::Block *blk) {
138 if (blockNamePrefixMap.count(blk) > 0)
return blockNamePrefixMap[blk];
143 p4configv1::P4Info *p4info) {
144 for (
auto &externType : *p4info->mutable_externs()) {
145 if (externType.extern_type_id() ==
static_cast<p4rt_id_t
>(typeId))
return &externType;
147 auto *externType = p4info->add_externs();
148 externType->set_extern_type_id(
static_cast<p4rt_id_t
>(typeId));
149 externType->set_extern_type_name(typeName);
155 const IR::IAnnotated *annotations,
156 const ::google::protobuf::Message &message,
157 p4configv1::P4Info *p4info,
158 cstring pipeName = cstring::empty) {
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);
167 externInstance->mutable_info()->PackFrom(message);
170 std::optional<ActionSelector> getActionSelector(
const IR::ExternBlock *instance) {
173 auto size = instance->getParameterValue(
"size"_cs);
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>()};
183 cstring pipeName = cstring::empty) {
184 ::dpdk::ActionSelector selector;
185 selector.set_max_group_size(actionSelector.maxGroupSize);
186 selector.set_num_groups(actionSelector.numGroups);
187 p4configv1::ActionProfile profile;
188 profile.set_size(actionSelector.size);
189 auto tablesIt = this->actionProfilesRefs.find(actionSelector.name);
190 if (tablesIt != this->actionProfilesRefs.end()) {
191 for (
const auto &table : tablesIt->second) {
192 profile.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
193 selector.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
198 cstring profileName = actionSelector.name;
199 selector.set_action_profile_id(
200 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
201 cstring selectorName = profileName +
"_sel";
202 addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(),
203 "ActionSelector"_cs, selectorName, actionSelector.annotations,
204 selector, p4Info, pipeName);
208 const IR::ExternBlock *externBlock)
override {
212 if (decl ==
nullptr)
return;
213 if (externBlock->type->name ==
"Digest") {
214 symbols->
add(SymbolType::P4RT_DIGEST(), decl);
216 auto selName = decl->controlPlaneName() +
"_sel";
217 auto profName = decl->controlPlaneName();
218 symbols->
add(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), selName);
219 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), profName);
224 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
227 auto tableDeclaration = tableBlock->container;
229 if (supportsTimeout) {
230 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
232 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
236 auto pipeName = getBlockNamePrefix(tableBlock);
237 auto *pre = table->mutable_preamble();
238 if (pre->name() == tableDeclaration->controlPlaneName())
239 pre->set_name(prefix(pipeName, pre->name()));
242 void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
243 const IR::ExternBlock *externBlock)
override {
244 P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
246 auto decl = externBlock->node->to<IR::Declaration_Instance>();
247 if (decl ==
nullptr)
return;
251 cstring pipeName = getBlockNamePrefix(externBlock);
253 auto p4RtTypeInfo = p4info->mutable_type_info();
254 if (externBlock->type->name ==
"Digest") {
255 auto digest =
getDigest(decl, p4RtTypeInfo);
256 if (digest) this->addDigest(symbols, p4info, *digest);
257 }
else if (externBlock->type->name ==
"ActionSelector") {
258 auto actionSelector = getActionSelector(externBlock);
259 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
260 for (
auto &extType : *p4info->mutable_action_profiles()) {
261 auto *pre = extType.mutable_preamble();
262 if (pre->name() == decl->controlPlaneName()) {
263 pre->set_name(prefix(pipeName, pre->name()));
267 }
else if (externBlock->type->name ==
"ActionProfile") {
268 for (
auto &extType : *p4info->mutable_action_profiles()) {
269 auto *pre = extType.mutable_preamble();
270 if (pre->name() == decl->controlPlaneName()) {
271 pre->set_name(prefix(pipeName, pre->name()));
275 }
else if (externBlock->type->name ==
"Meter") {
276 for (
auto &extType : *p4info->mutable_meters()) {
277 auto *pre = extType.mutable_preamble();
278 if (pre->name() == decl->controlPlaneName()) {
279 pre->set_name(prefix(pipeName, pre->name()));
283 }
else if (externBlock->type->name ==
"Counter") {
284 for (
auto &extType : *p4info->mutable_counters()) {
285 auto *pre = extType.mutable_preamble();
286 if (pre->name() == decl->controlPlaneName()) {
287 pre->set_name(prefix(pipeName, pre->name()));
291 }
else if (externBlock->type->name ==
"Register") {
292 for (
auto &extType : *p4info->mutable_registers()) {
293 auto *pre = extType.mutable_preamble();
294 if (pre->name() == decl->controlPlaneName()) {
295 pre->set_name(prefix(pipeName, pre->name()));
303 std::optional<Digest>
getDigest(
const IR::Declaration_Instance *decl,
304 p4configv1::P4TypeInfo *p4RtTypeInfo) {
305 BUG_CHECK(decl->type->is<IR::Type_Specialized>(),
"%1%: expected Type_Specialized",
307 auto type = decl->type->to<IR::Type_Specialized>();
308 BUG_CHECK(type->arguments->size() == 1,
"%1%: expected one type argument", decl);
309 auto typeArg = type->arguments->at(0);
312 BUG_CHECK(typeSpec !=
nullptr,
313 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
315 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
303 std::optional<Digest>
getDigest(
const IR::Declaration_Instance *decl, {
…}
321 auto timeout = table->properties->getProperty(
"psa_idle_timeout");
323 if (timeout ==
nullptr)
return false;
325 if (
auto exprValue = timeout->value->to<IR::ExpressionValue>()) {
326 if (
auto expr = exprValue->expression) {
327 if (
auto member = expr->to<IR::Member>()) {
328 if (member->member ==
"NOTIFY_CONTROL") {
330 }
else if (member->member ==
"NO_TIMEOUT") {
333 }
else if (expr->is<IR::PathExpression>()) {
334 ::error(ErrorType::ERR_UNEXPECTED,
335 "Unresolved value %1% for psa_idle_timeout "
336 "property on table %2%. Must be a constant and one of "
337 "{ NOTIFY_CONTROL, NO_TIMEOUT }",
344 ::error(ErrorType::ERR_UNEXPECTED,
345 "Unexpected value %1% for psa_idle_timeout "
346 "property on table %2%. Supported values are "
347 "{ NOTIFY_CONTROL, NO_TIMEOUT }",