7#ifndef CONTROL_PLANE_BFRUNTIME_H_
8#define CONTROL_PLANE_BFRUNTIME_H_
17#include "control-plane/p4RuntimeSerializer.h"
19#include "lib/error_catalog.h"
21#pragma GCC diagnostic push
22#pragma GCC diagnostic ignored "-Wunused-parameter"
23#pragma GCC diagnostic ignored "-Wpedantic"
24#include "p4/config/v1/p4info.pb.h"
25#pragma GCC diagnostic pop
27namespace p4configv1 = ::p4::config::v1;
40template <
typename T,
typename R>
41static inline constexpr P4Id makeBFRuntimeId(T base, R prefix) {
42 return static_cast<P4Id
>((base & 0xffffff) | (prefix << 24));
45static inline constexpr P4Id getIdPrefix(P4Id
id) {
return ((
id >> 24) & 0xff); }
47static inline Util::JsonObject *findJsonTable(Util::JsonArray *tablesJson, cstring tblName) {
48 for (
auto *t : *tablesJson) {
49 auto *tblObj = t->to<Util::JsonObject>();
50 auto tName = tblObj->getAs<Util::JsonValue>(
"name")->getString();
51 if (tName == tblName) {
58static inline Util::JsonObject *transformAnnotation(
const cstring &annotation) {
59 auto *annotationJson =
new Util::JsonObject();
62 annotationJson->emplace(
"name", annotation.escapeJson());
63 return annotationJson;
67static inline Util::JsonArray *transformAnnotations(
const It &first,
const It &last) {
68 auto *annotations =
new Util::JsonArray();
69 for (
auto it = first; it != last; it++) annotations->append(transformAnnotation(*it));
73static inline Util::JsonArray *transformAnnotations(
const p4configv1::Preamble &pre) {
74 return transformAnnotations(pre.annotations().begin(), pre.annotations().end());
79static inline bool isOfType(P4Id
id, T prefix) {
80 return getIdPrefix(
id) ==
static_cast<P4Id
>(prefix);
86static inline auto findP4InfoObject(
const It &first,
const It &last, P4Id objectId) ->
const
87 typename std::iterator_traits<It>::value_type * {
88 using T =
typename std::iterator_traits<It>::value_type;
89 auto desiredObject = std::find_if(
90 first, last, [&](
const T &
object) {
return object.preamble().id() == objectId; });
91 if (desiredObject == last)
return nullptr;
92 return &*desiredObject;
95static inline const p4configv1::Table *findTable(
const p4configv1::P4Info &p4info, P4Id tableId) {
96 const auto &tables = p4info.tables();
97 return findP4InfoObject(tables.begin(), tables.end(), tableId);
100static inline const p4configv1::Action *findAction(
const p4configv1::P4Info &p4info,
102 const auto &actions = p4info.actions();
103 return Standard::findP4InfoObject(actions.begin(), actions.end(), actionId);
106static inline const p4configv1::ActionProfile *findActionProf(
const p4configv1::P4Info &p4info,
108 const auto &actionProfs = p4info.action_profiles();
109 return findP4InfoObject(actionProfs.begin(), actionProfs.end(), actionProfId);
112static inline const p4configv1::DirectCounter *findDirectCounter(
const p4configv1::P4Info &p4info,
114 const auto &counters = p4info.direct_counters();
115 return findP4InfoObject(counters.begin(), counters.end(), counterId);
118static inline const p4configv1::DirectMeter *findDirectMeter(
const p4configv1::P4Info &p4info,
120 const auto &meters = p4info.direct_meters();
121 return findP4InfoObject(meters.begin(), meters.end(), meterId);
126static inline Util::JsonObject *makeType(cstring type) {
127 auto *typeObj =
new Util::JsonObject();
128 typeObj->emplace(
"type", type);
132template <typename T, typename std::enable_if<std::is_integral<T>::value,
int>::type = 0>
133static inline Util::JsonObject *makeType(cstring type, T defaultValue) {
134 auto *typeObj =
new Util::JsonObject();
135 typeObj->emplace(
"type", type);
136 typeObj->emplace(
"default_value", defaultValue);
140static inline Util::JsonObject *makeTypeBool(std::optional<bool> defaultValue = std::nullopt) {
141 auto *typeObj =
new Util::JsonObject();
142 typeObj->emplace(
"type",
"bool");
143 if (defaultValue != std::nullopt) typeObj->emplace(
"default_value", *defaultValue);
147static inline Util::JsonObject *makeTypeBytes(
int width,
148 std::optional<int64_t> defaultValue = std::nullopt) {
149 auto *typeObj =
new Util::JsonObject();
150 typeObj->emplace(
"type",
"bytes");
151 typeObj->emplace(
"width", width);
152 if (defaultValue != std::nullopt) typeObj->emplace(
"default_value", *defaultValue);
156static inline Util::JsonObject *makeTypeEnum(
const std::vector<cstring> &choices,
157 std::optional<cstring> defaultValue = std::nullopt) {
158 auto *typeObj =
new Util::JsonObject();
159 typeObj->emplace(
"type",
"string");
160 auto *choicesArray =
new Util::JsonArray();
161 for (
auto choice : choices) choicesArray->append(choice);
162 typeObj->emplace(
"choices", choicesArray);
163 if (defaultValue != std::nullopt) typeObj->emplace(
"default_value", *defaultValue);
167static inline void addSingleton(Util::JsonArray *dataJson, Util::JsonObject *dataField,
168 bool mandatory,
bool readOnly) {
169 auto *singletonJson =
new Util::JsonObject();
170 singletonJson->emplace(
"mandatory", mandatory);
171 singletonJson->emplace(
"read_only", readOnly);
172 singletonJson->emplace(
"singleton", dataField);
173 dataJson->append(singletonJson);
176static inline void addOneOf(Util::JsonArray *dataJson, Util::JsonArray *choicesJson,
bool mandatory,
178 auto *oneOfJson =
new Util::JsonObject();
179 oneOfJson->emplace(
"mandatory", mandatory);
180 oneOfJson->emplace(
"read_only", readOnly);
181 oneOfJson->emplace(
"oneof", choicesJson);
182 dataJson->append(oneOfJson);
186static inline std::optional<cstring> transformMatchType(
187 p4configv1::MatchField_MatchType matchType) {
189 case p4configv1::MatchField_MatchType_UNSPECIFIED:
191 case p4configv1::MatchField_MatchType_EXACT:
193 case p4configv1::MatchField_MatchType_LPM:
195 case p4configv1::MatchField_MatchType_TERNARY:
197 case p4configv1::MatchField_MatchType_RANGE:
199 case p4configv1::MatchField_MatchType_OPTIONAL:
200 return "Optional"_cs;
207static inline std::optional<cstring> transformOtherMatchType(std::string matchType) {
208 if (matchType ==
"atcam_partition_index")
return "ATCAM"_cs;
209 if (matchType ==
"dleft_hash")
return "DLEFT_HASH"_cs;
214template <
typename It>
215static std::vector<P4Id> collectTableIds(
const p4configv1::P4Info &p4info,
const It &first,
217 std::vector<P4Id> tableIds;
218 for (
auto it = first; it != last; it++) {
219 auto *table = Standard::findTable(p4info, *it);
220 if (table ==
nullptr) {
221 ::P4::error(ErrorType::ERR_INVALID,
"Invalid table id '%1%'", *it);
224 tableIds.push_back(*it);
232class TypeSpecParser {
240 using Fields = std::vector<Field>;
241 using iterator = Fields::iterator;
242 using const_iterator = Fields::const_iterator;
244 static TypeSpecParser make(
const p4configv1::P4Info &p4info,
245 const p4configv1::P4DataTypeSpec &typeSpec,
cstring instanceType,
247 const std::vector<cstring> *fieldNames =
nullptr,
251 iterator begin() {
return fields.begin(); }
253 iterator end() {
return fields.end(); }
254 const_iterator cend() {
return fields.cend(); }
255 size_t size() {
return fields.size(); }
258 explicit TypeSpecParser(Fields &&fields) : fields(std::move(fields)) {}
263class BFRuntimeGenerator {
265 virtual ~BFRuntimeGenerator() =
default;
266 explicit BFRuntimeGenerator(
const p4configv1::P4Info &p4info) : p4info(p4info) {}
279 enum TDDataFieldIds : P4Id {
282 TD_DATA_START = (1 << 16),
284 TD_DATA_MATCH_PRIORITY,
287 TD_DATA_ACTION_MEMBER_ID,
288 TD_DATA_SELECTOR_GROUP_ID,
289 TD_DATA_ACTION_MEMBER_STATUS,
290 TD_DATA_MAX_GROUP_SIZE,
293 TD_DATA_ENTRY_HIT_STATE,
295 TD_DATA_METER_SPEC_CIR_KBPS,
296 TD_DATA_METER_SPEC_PIR_KBPS,
297 TD_DATA_METER_SPEC_CBS_KBITS,
298 TD_DATA_METER_SPEC_PBS_KBITS,
300 TD_DATA_METER_SPEC_CIR_PPS,
301 TD_DATA_METER_SPEC_PIR_PPS,
302 TD_DATA_METER_SPEC_CBS_PKTS,
303 TD_DATA_METER_SPEC_PBS_PKTS,
305 TD_DATA_COUNTER_SPEC_BYTES,
306 TD_DATA_COUNTER_SPEC_PKTS,
309 TD_DATA_COUNTER_INDEX,
310 TD_DATA_REGISTER_INDEX,
317 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2, BOTH = 3 };
324 static std::optional<Counter> from(
const p4configv1::Counter &counterInstance);
325 static std::optional<Counter> fromDirect(
const p4configv1::DirectCounter &counterInstance);
330 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2 };
331 enum Type { COLOR_UNAWARE = 0, COLOR_AWARE = 1 };
338 static std::optional<Meter> from(
const p4configv1::Meter &meterInstance);
339 static std::optional<Meter> fromDirect(
const p4configv1::DirectMeter &meterInstance);
348 std::vector<P4Id> tableIds;
350 static P4Id makeActProfId(P4Id implementationId);
351 static std::optional<ActionProf> from(
const p4configv1::P4Info &p4info,
352 const p4configv1::ActionProfile &actionProfile);
359 p4configv1::P4DataTypeSpec typeSpec;
362 static std::optional<Digest> from(
const p4configv1::Digest &digest);
368 std::string dataFieldName;
371 p4configv1::P4DataTypeSpec typeSpec;
374 static std::optional<Register> from(
const p4configv1::Register ®Instance);
378 virtual bool addMatchTypePriority(std::optional<cstring> &matchType)
const;
381 virtual bool addActionProfIds(
const p4configv1::Table &table,
393 virtual void addDirectResources(
const p4configv1::Table &table,
Util::JsonArray *dataJson,
396 P4Id maxActionParamId = 0)
const;
398 virtual std::optional<bool> actProfHasSelector(P4Id actProfId)
const;
405 P4Id *maxActionParamId =
nullptr)
const;
406 virtual std::optional<Counter> getDirectCounter(P4Id counterId)
const;
407 virtual std::optional<Meter> getDirectMeter(P4Id meterId)
const;
418 const p4configv1::P4DataTypeSpec &typeSpec,
420 const std::vector<cstring> *fieldNames =
nullptr,
422 cstring suffix = cstring::empty, P4Id idOffset = 1)
const;
433 static void addActionDataField(
Util::JsonArray *dataJson, P4Id
id,
const std::string &name,
452 P4Id idOffset = 1)
const;
454 const p4configv1::P4Info &p4info;
void addRegisterDataFields(Util::JsonArray *dataJson, const Register ®ister_, P4Id idOffset=1) const
Definition control-plane/bfruntime.cpp:402
void serializeBFRuntimeSchema(std::ostream *destination)
Definition control-plane/bfruntime.cpp:864
virtual const Util::JsonObject * genSchema() const
Generates the schema as a Json object for the provided P4Info instance.
Definition control-plane/bfruntime.cpp:843
void transformTypeSpecToDataFields(Util::JsonArray *fieldsJson, const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType, cstring instanceName, const std::vector< cstring > *fieldNames=nullptr, cstring prefix=cstring::empty, cstring suffix=cstring::empty, P4Id idOffset=1) const
Definition control-plane/bfruntime.cpp:388
Util::JsonArray * makeActionSpecs(const p4configv1::Table &table, P4Id *maxActionParamId=nullptr) const
Definition control-plane/bfruntime.cpp:532
Definition control-plane/bfruntime.h:234
Definition lib/json.h:128
Definition lib/json.h:177
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58
Definition control-plane/bfruntime.h:344
Common counter representation between PSA and other architectures.
Definition control-plane/bfruntime.h:316
Common digest representation between PSA and other architectures.
Definition control-plane/bfruntime.h:356
Common meter representation between PSA and other architectures.
Definition control-plane/bfruntime.h:329
Common register representation between PSA and other architectures.
Definition control-plane/bfruntime.h:366
Definition p4RuntimeSerializer.h:48
Definition register_reference.h:28