90 std::unordered_map<const IR::Block *, cstring> blockNamePrefixMap;
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();
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,
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);
167 externInstance->mutable_info()->PackFrom(message);
170 std::optional<ActionSelector> getActionSelector(
const IR::ExternBlock *instance) {
171 auto actionSelDecl = instance->node->to<IR::IDeclaration>();
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>()};
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));
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,
207 const IR::ExternBlock *externBlock)
override {
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);
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);
223 p4configv1::Table *table,
const IR::TableBlock *tableBlock)
override {
226 auto tableDeclaration = tableBlock->container;
228 if (supportsTimeout) {
229 table->set_idle_timeout_behavior(p4configv1::Table::NOTIFY_CONTROL);
231 table->set_idle_timeout_behavior(p4configv1::Table::NO_TIMEOUT);
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()));
241 void addExternInstance(
const P4RuntimeSymbolTableIface &symbols, p4configv1::P4Info *p4info,
242 const IR::ExternBlock *externBlock)
override {
243 P4RuntimeArchHandlerCommon<arch>::addExternInstance(symbols, p4info, externBlock);
245 auto decl = externBlock->node->to<IR::Declaration_Instance>();
246 if (decl ==
nullptr)
return;
250 cstring pipeName = getBlockNamePrefix(externBlock);
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()));
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()));
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()));
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()));
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()));
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",
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);
311 BUG_CHECK(typeSpec !=
nullptr,
312 "P4 type %1% could not be converted to P4Info P4DataTypeSpec");
314 return Digest{decl->controlPlaneName(), typeSpec, decl->to<IR::IAnnotated>()};
320 auto timeout = table->properties->getProperty(
"psa_idle_timeout");
322 if (timeout ==
nullptr)
return false;
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") {
329 }
else if (member->member ==
"NO_TIMEOUT") {
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 }",
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 }",