P4C
The P4 Compiler
Loading...
Searching...
No Matches
control-plane/bfruntime.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 CONTROL_PLANE_BFRUNTIME_H_
16#define CONTROL_PLANE_BFRUNTIME_H_
17
18#include <algorithm>
19#include <iosfwd>
20#include <iterator>
21#include <optional>
22#include <ostream>
23#include <string>
24
25#include "control-plane/p4RuntimeSerializer.h"
26#include "lib/error.h"
27#include "lib/error_catalog.h"
28#include "lib/json.h"
29#pragma GCC diagnostic push
30#pragma GCC diagnostic ignored "-Wunused-parameter"
31#pragma GCC diagnostic ignored "-Wpedantic"
32#include "p4/config/v1/p4info.pb.h"
33#pragma GCC diagnostic pop
34
35namespace p4configv1 = ::p4::config::v1;
36
37namespace P4 {
38struct P4RuntimeAPI;
39} // namespace P4
40
41namespace P4 {
42
43namespace BFRT {
44
45using P4Id = uint32_t;
46
47// Helpers
48template <typename T, typename R>
49static inline constexpr P4Id makeBFRuntimeId(T base, R prefix) {
50 return static_cast<P4Id>((base & 0xffffff) | (prefix << 24));
51}
52
53static inline constexpr P4Id getIdPrefix(P4Id id) { return ((id >> 24) & 0xff); }
54
55static inline Util::JsonObject *findJsonTable(Util::JsonArray *tablesJson, cstring tblName) {
56 for (auto *t : *tablesJson) {
57 auto *tblObj = t->to<Util::JsonObject>();
58 auto tName = tblObj->getAs<Util::JsonValue>("name")->getString();
59 if (tName == tblName) {
60 return tblObj;
61 }
62 }
63 return nullptr;
64}
65
66static inline Util::JsonObject *transformAnnotation(const cstring &annotation) {
67 auto *annotationJson = new Util::JsonObject();
68 // TODO(antonin): annotation string will need to be parsed so we can have it
69 // in key/value format here.
70 annotationJson->emplace("name", annotation.escapeJson());
71 return annotationJson;
72}
73
74template <typename It>
75static inline Util::JsonArray *transformAnnotations(const It &first, const It &last) {
76 auto *annotations = new Util::JsonArray();
77 for (auto it = first; it != last; it++) annotations->append(transformAnnotation(*it));
78 return annotations;
79}
80
81static inline Util::JsonArray *transformAnnotations(const p4configv1::Preamble &pre) {
82 return transformAnnotations(pre.annotations().begin(), pre.annotations().end());
83}
84
86template <typename T>
87static inline bool isOfType(P4Id id, T prefix) {
88 return getIdPrefix(id) == static_cast<P4Id>(prefix);
89}
90
91namespace Standard {
92
93template <typename It>
94static inline auto findP4InfoObject(const It &first, const It &last, P4Id objectId) -> const
95 typename std::iterator_traits<It>::value_type * {
96 using T = typename std::iterator_traits<It>::value_type;
97 auto desiredObject = std::find_if(
98 first, last, [&](const T &object) { return object.preamble().id() == objectId; });
99 if (desiredObject == last) return nullptr;
100 return &*desiredObject;
101}
102
103static inline const p4configv1::Table *findTable(const p4configv1::P4Info &p4info, P4Id tableId) {
104 const auto &tables = p4info.tables();
105 return findP4InfoObject(tables.begin(), tables.end(), tableId);
106}
107
108static inline const p4configv1::Action *findAction(const p4configv1::P4Info &p4info,
109 P4Id actionId) {
110 const auto &actions = p4info.actions();
111 return Standard::findP4InfoObject(actions.begin(), actions.end(), actionId);
112}
113
114static inline const p4configv1::ActionProfile *findActionProf(const p4configv1::P4Info &p4info,
115 P4Id actionProfId) {
116 const auto &actionProfs = p4info.action_profiles();
117 return findP4InfoObject(actionProfs.begin(), actionProfs.end(), actionProfId);
118}
119
120static inline const p4configv1::DirectCounter *findDirectCounter(const p4configv1::P4Info &p4info,
121 P4Id counterId) {
122 const auto &counters = p4info.direct_counters();
123 return findP4InfoObject(counters.begin(), counters.end(), counterId);
124}
125
126static inline const p4configv1::DirectMeter *findDirectMeter(const p4configv1::P4Info &p4info,
127 P4Id meterId) {
128 const auto &meters = p4info.direct_meters();
129 return findP4InfoObject(meters.begin(), meters.end(), meterId);
130}
131
132} // namespace Standard
133
134static inline Util::JsonObject *makeType(cstring type) {
135 auto *typeObj = new Util::JsonObject();
136 typeObj->emplace("type", type);
137 return typeObj;
138}
139
140template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
141static inline Util::JsonObject *makeType(cstring type, T defaultValue) {
142 auto *typeObj = new Util::JsonObject();
143 typeObj->emplace("type", type);
144 typeObj->emplace("default_value", defaultValue);
145 return typeObj;
146}
147
148static inline Util::JsonObject *makeTypeBool(std::optional<bool> defaultValue = std::nullopt) {
149 auto *typeObj = new Util::JsonObject();
150 typeObj->emplace("type", "bool");
151 if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue);
152 return typeObj;
153}
154
155static inline Util::JsonObject *makeTypeBytes(int width,
156 std::optional<int64_t> defaultValue = std::nullopt) {
157 auto *typeObj = new Util::JsonObject();
158 typeObj->emplace("type", "bytes");
159 typeObj->emplace("width", width);
160 if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue);
161 return typeObj;
162}
163
164static inline Util::JsonObject *makeTypeEnum(const std::vector<cstring> &choices,
165 std::optional<cstring> defaultValue = std::nullopt) {
166 auto *typeObj = new Util::JsonObject();
167 typeObj->emplace("type", "string");
168 auto *choicesArray = new Util::JsonArray();
169 for (auto choice : choices) choicesArray->append(choice);
170 typeObj->emplace("choices", choicesArray);
171 if (defaultValue != std::nullopt) typeObj->emplace("default_value", *defaultValue);
172 return typeObj;
173}
174
175static inline void addSingleton(Util::JsonArray *dataJson, Util::JsonObject *dataField,
176 bool mandatory, bool readOnly) {
177 auto *singletonJson = new Util::JsonObject();
178 singletonJson->emplace("mandatory", mandatory);
179 singletonJson->emplace("read_only", readOnly);
180 singletonJson->emplace("singleton", dataField);
181 dataJson->append(singletonJson);
182}
183
184static inline void addOneOf(Util::JsonArray *dataJson, Util::JsonArray *choicesJson, bool mandatory,
185 bool readOnly) {
186 auto *oneOfJson = new Util::JsonObject();
187 oneOfJson->emplace("mandatory", mandatory);
188 oneOfJson->emplace("read_only", readOnly);
189 oneOfJson->emplace("oneof", choicesJson);
190 dataJson->append(oneOfJson);
191}
192
193// FIXME: Switch to std::string_view
194static inline std::optional<cstring> transformMatchType(
195 p4configv1::MatchField_MatchType matchType) {
196 switch (matchType) {
197 case p4configv1::MatchField_MatchType_UNSPECIFIED:
198 return std::nullopt;
199 case p4configv1::MatchField_MatchType_EXACT:
200 return "Exact"_cs;
201 case p4configv1::MatchField_MatchType_LPM:
202 return "LPM"_cs;
203 case p4configv1::MatchField_MatchType_TERNARY:
204 return "Ternary"_cs;
205 case p4configv1::MatchField_MatchType_RANGE:
206 return "Range"_cs;
207 case p4configv1::MatchField_MatchType_OPTIONAL:
208 return "Optional"_cs;
209 default:
210 return std::nullopt;
211 }
212}
213
214// FIXME: Switch to std::string_view
215static inline std::optional<cstring> transformOtherMatchType(std::string matchType) {
216 if (matchType == "atcam_partition_index") return "ATCAM"_cs;
217 if (matchType == "dleft_hash") return "DLEFT_HASH"_cs;
218
219 return std::nullopt;
220}
221
222template <typename It>
223static std::vector<P4Id> collectTableIds(const p4configv1::P4Info &p4info, const It &first,
224 const It &last) {
225 std::vector<P4Id> tableIds;
226 for (auto it = first; it != last; it++) {
227 auto *table = Standard::findTable(p4info, *it);
228 if (table == nullptr) {
229 ::P4::error(ErrorType::ERR_INVALID, "Invalid table id '%1%'", *it);
230 continue;
231 }
232 tableIds.push_back(*it);
233 }
234 return tableIds;
235}
236
241 public:
242 struct Field {
243 cstring name;
244 P4Id id;
245 Util::JsonObject *type;
246 };
247
248 using Fields = std::vector<Field>;
249 using iterator = Fields::iterator;
250 using const_iterator = Fields::const_iterator;
251
252 static TypeSpecParser make(const p4configv1::P4Info &p4info,
253 const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType,
254 cstring instanceName,
255 const std::vector<cstring> *fieldNames = nullptr,
256 cstring prefix = cstring::empty, cstring suffix = cstring::empty,
257 P4Id idOffset = 1);
258
259 iterator begin() { return fields.begin(); }
260 const_iterator cbegin() { return fields.cbegin(); }
261 iterator end() { return fields.end(); }
262 const_iterator cend() { return fields.cend(); }
263 size_t size() { return fields.size(); }
264
265 private:
266 explicit TypeSpecParser(Fields &&fields) : fields(std::move(fields)) {}
267
268 Fields fields;
269};
270
272 public:
273 explicit BFRuntimeGenerator(const p4configv1::P4Info &p4info) : p4info(p4info) {}
274
276 virtual const Util::JsonObject *genSchema() const;
277
280 void serializeBFRuntimeSchema(std::ostream *destination);
281
282 protected:
283 // To avoid potential clashes with P4 names, we prefix the names of "fixed"
284 // data field with a '$'. For example, for TD_DATA_ACTION_MEMBER_ID, we
285 // use the name $ACTION_MEMBER_ID.
286 enum TDDataFieldIds : P4Id {
287 // ids for fixed data fields must not collide with the auto-generated
288 // ids for P4 fields (e.g. match key fields).
289 TD_DATA_START = (1 << 16),
290
291 TD_DATA_MATCH_PRIORITY,
292
293 TD_DATA_ACTION,
294 TD_DATA_ACTION_MEMBER_ID,
295 TD_DATA_SELECTOR_GROUP_ID,
296 TD_DATA_ACTION_MEMBER_STATUS,
297 TD_DATA_MAX_GROUP_SIZE,
298
299 TD_DATA_ENTRY_TTL,
300 TD_DATA_ENTRY_HIT_STATE,
301
302 TD_DATA_METER_SPEC_CIR_KBPS,
303 TD_DATA_METER_SPEC_PIR_KBPS,
304 TD_DATA_METER_SPEC_CBS_KBITS,
305 TD_DATA_METER_SPEC_PBS_KBITS,
306
307 TD_DATA_METER_SPEC_CIR_PPS,
308 TD_DATA_METER_SPEC_PIR_PPS,
309 TD_DATA_METER_SPEC_CBS_PKTS,
310 TD_DATA_METER_SPEC_PBS_PKTS,
311
312 TD_DATA_COUNTER_SPEC_BYTES,
313 TD_DATA_COUNTER_SPEC_PKTS,
314
315 TD_DATA_METER_INDEX,
316 TD_DATA_COUNTER_INDEX,
317 TD_DATA_REGISTER_INDEX,
318
319 TD_DATA_END,
320 };
321
323 struct Counter {
324 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2, BOTH = 3 };
325 std::string name;
326 P4Id id;
327 int64_t size;
328 Unit unit;
329 Util::JsonArray *annotations;
330
331 static std::optional<Counter> from(const p4configv1::Counter &counterInstance);
332 static std::optional<Counter> fromDirect(const p4configv1::DirectCounter &counterInstance);
333 };
334
336 struct Meter {
337 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2 };
338 enum Type { COLOR_UNAWARE = 0, COLOR_AWARE = 1 };
339 std::string name;
340 P4Id id;
341 int64_t size;
342 Unit unit;
343 Util::JsonArray *annotations;
344
345 static std::optional<Meter> from(const p4configv1::Meter &meterInstance);
346 static std::optional<Meter> fromDirect(const p4configv1::DirectMeter &meterInstance);
347 };
348
351 struct ActionProf {
352 std::string name;
353 P4Id id;
354 int64_t size;
355 std::vector<P4Id> tableIds;
356 Util::JsonArray *annotations;
357 static P4Id makeActProfId(P4Id implementationId);
358 static std::optional<ActionProf> from(const p4configv1::P4Info &p4info,
359 const p4configv1::ActionProfile &actionProfile);
360 };
361
363 struct Digest {
364 std::string name;
365 P4Id id;
366 p4configv1::P4DataTypeSpec typeSpec;
367 Util::JsonArray *annotations;
368
369 static std::optional<Digest> from(const p4configv1::Digest &digest);
370 };
371
373 struct Register {
374 std::string name;
375 std::string dataFieldName;
376 P4Id id;
377 int64_t size;
378 p4configv1::P4DataTypeSpec typeSpec;
379 Util::JsonArray *annotations;
380
381 static std::optional<Register> from(const p4configv1::Register &regInstance);
382 };
383
384 void addMatchTables(Util::JsonArray *tablesJson) const;
385 virtual bool addMatchTypePriority(std::optional<cstring> &matchType) const;
386 virtual void addConstTableAttr(Util::JsonArray *attrJson) const;
387 virtual void addActionProfs(Util::JsonArray *tablesJson) const;
388 virtual bool addActionProfIds(const p4configv1::Table &table,
389 Util::JsonObject *tableJson) const;
390 void addCounters(Util::JsonArray *tablesJson) const;
391 void addMeters(Util::JsonArray *tablesJson) const;
392 void addRegisters(Util::JsonArray *tablesJson) const;
393
394 void addCounterCommon(Util::JsonArray *tablesJson, const Counter &counter) const;
395 void addMeterCommon(Util::JsonArray *tablesJson, const Meter &meter) const;
396 void addRegisterCommon(Util::JsonArray *tablesJson, const Register &reg) const;
397 void addActionProfCommon(Util::JsonArray *tablesJson, const ActionProf &actionProf) const;
398 void addLearnFilters(Util::JsonArray *learnFiltersJson) const;
399 void addLearnFilterCommon(Util::JsonArray *learnFiltersJson, const Digest &digest) const;
400 virtual void addDirectResources(const p4configv1::Table &table, Util::JsonArray *dataJson,
401 Util::JsonArray *operationsJson,
402 Util::JsonArray *attributesJson,
403 P4Id maxActionParamId = 0) const;
404
405 virtual std::optional<bool> actProfHasSelector(P4Id actProfId) const;
411 Util::JsonArray *makeActionSpecs(const p4configv1::Table &table,
412 P4Id *maxActionParamId = nullptr) const;
413 virtual std::optional<Counter> getDirectCounter(P4Id counterId) const;
414 virtual std::optional<Meter> getDirectMeter(P4Id meterId) const;
415
425 const p4configv1::P4DataTypeSpec &typeSpec,
426 cstring instanceType, cstring instanceName,
427 const std::vector<cstring> *fieldNames = nullptr,
428 cstring prefix = cstring::empty,
429 cstring suffix = cstring::empty, P4Id idOffset = 1) const;
430
431 static void addMeterDataFields(Util::JsonArray *dataJson, const Meter &meter);
432 static Util::JsonObject *makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type,
433 bool repeated,
434 Util::JsonArray *annotations = nullptr);
435
436 static Util::JsonObject *makeContainerDataField(P4Id id, cstring name, Util::JsonArray *items,
437 bool repeated,
438 Util::JsonArray *annotations = nullptr);
439
440 static void addActionDataField(Util::JsonArray *dataJson, P4Id id, const std::string &name,
441 bool mandatory, bool read_only, Util::JsonObject *type,
442 Util::JsonArray *annotations = nullptr);
443
444 static void addKeyField(Util::JsonArray *dataJson, P4Id id, cstring name, bool mandatory,
445 cstring matchType, Util::JsonObject *type,
446 Util::JsonArray *annotations = nullptr);
447
448 static void addCounterDataFields(Util::JsonArray *dataJson, const Counter &counter);
449
450 static Util::JsonObject *initTableJson(const std::string &name, P4Id id, cstring tableType,
451 int64_t size, Util::JsonArray *annotations = nullptr);
452
453 static void addToDependsOn(Util::JsonObject *tableJson, P4Id id);
454
458 void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_,
459 P4Id idOffset = 1) const;
460
461 const p4configv1::P4Info &p4info;
462};
463
464} // namespace BFRT
465
466} // namespace P4
467
468#endif /* CONTROL_PLANE_BFRUNTIME_H_ */
Definition control-plane/bfruntime.h:271
void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_, P4Id idOffset=1) const
Definition control-plane/bfruntime.cpp:412
void serializeBFRuntimeSchema(std::ostream *destination)
Definition control-plane/bfruntime.cpp:874
virtual const Util::JsonObject * genSchema() const
Generates the schema as a Json object for the provided P4Info instance.
Definition control-plane/bfruntime.cpp:853
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:398
Util::JsonArray * makeActionSpecs(const p4configv1::Table &table, P4Id *maxActionParamId=nullptr) const
Definition control-plane/bfruntime.cpp:542
Definition control-plane/bfruntime.h:240
Definition control-plane/bfruntime.h:242
Definition json.h:115
Definition json.h:164
Definition cstring.h:85
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51
STL namespace.
Definition control-plane/bfruntime.h:351
Common counter representation between PSA and other architectures.
Definition control-plane/bfruntime.h:323
Common digest representation between PSA and other architectures.
Definition control-plane/bfruntime.h:363
Common meter representation between PSA and other architectures.
Definition control-plane/bfruntime.h:336
Common register representation between PSA and other architectures.
Definition control-plane/bfruntime.h:373