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();
96 ::P4::error(ErrorType::ERR_NOT_FOUND,
"Program does not contain a `main` module");
97 auto cparams = main->getConstructorParameters();
99 for (
auto param : main->constantValue) {
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>());
115 using Counter = p4configv1::Counter;
116 using Meter = p4configv1::Meter;
117 using CounterSpec = p4configv1::CounterSpec;
118 using MeterSpec = p4configv1::MeterSpec;
121 const IR::ToplevelBlock *evaluatedProgram)
128 forAllPipeBlocks(evaluatedProgram, [&](
cstring pipeName,
const IR::PackageBlock *pkg) {
130 auto decl = pkg->node->to<IR::Declaration_Instance>();
131 cstring blockNamePrefix = pipeName;
132 if (decl) blockNamePrefix = decl->controlPlaneName();
133 blockNamePrefixMap[block] = blockNamePrefix;
138 cstring getBlockNamePrefix(
const IR::Block *blk) {
139 if (blockNamePrefixMap.count(blk) > 0)
return blockNamePrefixMap[blk];
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;
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);
156 const IR::IAnnotated *annotations,
157 const ::google::protobuf::Message &message,
158 p4configv1::P4Info *p4info,
159 cstring pipeName = cstring::empty) {
160 auto *externType = getP4InfoExtern(typeId, typeName, p4info);
161 auto *externInstance = externType->add_instances();
162 auto *pre = externInstance->mutable_preamble();
163 pre->set_id(symbols.
getId(typeId, name));
164 pre->set_name(prefix(pipeName, name));
165 pre->set_alias(symbols.
getAlias(name));
166 Helpers::addAnnotations(pre, annotations);
168 externInstance->mutable_info()->PackFrom(message);
171 std::optional<ActionSelector> getActionSelector(
const IR::ExternBlock *instance) {
174 auto size = instance->getParameterValue(
"size"_cs);
175 BUG_CHECK(size->
is<IR::Constant>(),
"Non-constant size");
176 return ActionSelector{actionSelDecl->controlPlaneName(), size->
to<IR::Constant>()->asInt(),
177 ActionSelector::defaultMaxGroupSize,
178 size->
to<IR::Constant>()->asInt(),
179 actionSelDecl->to<IR::IAnnotated>()};
184 cstring pipeName = cstring::empty) {
185 ::dpdk::ActionSelector selector;
186 selector.set_max_group_size(actionSelector.maxGroupSize);
187 selector.set_num_groups(actionSelector.numGroups);
188 p4configv1::ActionProfile profile;
189 profile.set_size(actionSelector.size);
190 auto tablesIt = this->actionProfilesRefs.find(actionSelector.name);
191 if (tablesIt != this->actionProfilesRefs.end()) {
192 for (
const auto &table : tablesIt->second) {
193 profile.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
194 selector.add_table_ids(symbols.
getId(P4RuntimeSymbolType::P4RT_TABLE(), table));
199 cstring profileName = actionSelector.name;
200 selector.set_action_profile_id(
201 symbols.
getId(SymbolType::P4RT_ACTION_PROFILE(), profileName));
202 cstring selectorName = profileName +
"_sel";
203 addP4InfoExternInstance(symbols, SymbolTypeDPDK::P4RT_ACTION_SELECTOR(),
204 "ActionSelector"_cs, selectorName, actionSelector.annotations,
205 selector, p4Info, pipeName);
209 const IR::ExternBlock *externBlock)
override {
213 if (decl ==
nullptr)
return;
214 if (externBlock->type->name ==
"Digest") {
215 symbols->
add(SymbolType::P4RT_DIGEST(), decl);
217 auto selName = decl->controlPlaneName() +
"_sel";
218 auto profName = decl->controlPlaneName();
219 symbols->
add(SymbolTypeDPDK::P4RT_ACTION_SELECTOR(), selName);
220 symbols->
add(SymbolType::P4RT_ACTION_PROFILE(), profName);
225 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
228 auto tableDeclaration = tableBlock->container;
230 if (supportsTimeout) {
231 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
233 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
237 auto pipeName = getBlockNamePrefix(tableBlock);
238 auto *pre = table->mutable_preamble();
239 if (pre->name() == tableDeclaration->controlPlaneName())
240 pre->set_name(prefix(pipeName, pre->name()));
243 void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
244 const IR::ExternBlock *externBlock)
override {
245 P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
247 auto decl = externBlock->node->to<IR::Declaration_Instance>();
248 if (decl ==
nullptr)
return;
252 cstring pipeName = getBlockNamePrefix(externBlock);
254 auto p4RtTypeInfo = p4info->mutable_type_info();
255 if (externBlock->type->name ==
"Digest") {
256 auto digest =
getDigest(decl, p4RtTypeInfo);
257 if (digest) this->addDigest(symbols, p4info, *digest);
258 }
else if (externBlock->type->name ==
"ActionSelector") {
259 auto actionSelector = getActionSelector(externBlock);
260 if (actionSelector) addActionSelector(symbols, p4info, *actionSelector, pipeName);
261 for (
auto &extType : *p4info->mutable_action_profiles()) {
262 auto *pre = extType.mutable_preamble();
263 if (pre->name() == decl->controlPlaneName()) {
264 pre->set_name(prefix(pipeName, pre->name()));
268 }
else if (externBlock->type->name ==
"ActionProfile") {
269 for (
auto &extType : *p4info->mutable_action_profiles()) {
270 auto *pre = extType.mutable_preamble();
271 if (pre->name() == decl->controlPlaneName()) {
272 pre->set_name(prefix(pipeName, pre->name()));
276 }
else if (externBlock->type->name ==
"Meter") {
277 for (
auto &extType : *p4info->mutable_meters()) {
278 auto *pre = extType.mutable_preamble();
279 if (pre->name() == decl->controlPlaneName()) {
280 pre->set_name(prefix(pipeName, pre->name()));
284 }
else if (externBlock->type->name ==
"Counter") {
285 for (
auto &extType : *p4info->mutable_counters()) {
286 auto *pre = extType.mutable_preamble();
287 if (pre->name() == decl->controlPlaneName()) {
288 pre->set_name(prefix(pipeName, pre->name()));
292 }
else if (externBlock->type->name ==
"Register") {
293 for (
auto &extType : *p4info->mutable_registers()) {
294 auto *pre = extType.mutable_preamble();
295 if (pre->name() == decl->controlPlaneName()) {
296 pre->set_name(prefix(pipeName, pre->name()));
304 std::optional<Digest>
getDigest(
const IR::Declaration_Instance *decl,
305 p4configv1::P4TypeInfo *p4RtTypeInfo) {
306 BUG_CHECK(decl->type->is<IR::Type_Specialized>(),
"%1%: expected Type_Specialized",
308 auto type = decl->type->to<IR::Type_Specialized>();
309 BUG_CHECK(type->arguments->size() == 1,
"%1%: expected one type argument", decl);
310 auto typeArg = type->arguments->at(0);
313 BUG_CHECK(typeSpec !=
nullptr,
314 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
316 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
322 auto timeout = table->properties->getProperty(
"psa_idle_timeout");
324 if (timeout ==
nullptr)
return false;
326 if (
auto exprValue = timeout->value->to<IR::ExpressionValue>()) {
327 if (
auto expr = exprValue->expression) {
328 if (
auto member = expr->to<IR::Member>()) {
329 if (member->member ==
"NOTIFY_CONTROL") {
331 }
else if (member->member ==
"NO_TIMEOUT") {
334 }
else if (expr->is<IR::PathExpression>()) {
336 "Unresolved value %1% for psa_idle_timeout "
337 "property on table %2%. Must be a constant and one of "
338 "{ NOTIFY_CONTROL, NO_TIMEOUT }",
346 "Unexpected value %1% for psa_idle_timeout "
347 "property on table %2%. Supported values are "
348 "{ NOTIFY_CONTROL, NO_TIMEOUT }",