P4C
The P4 Compiler
 
Loading...
Searching...
No Matches
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->get("name")->to<Util::JsonValue>()->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
193static inline std::optional<cstring> transformMatchType(
194 p4configv1::MatchField_MatchType matchType) {
195 switch (matchType) {
196 case p4configv1::MatchField_MatchType_UNSPECIFIED:
197 return std::nullopt;
198 case p4configv1::MatchField_MatchType_EXACT:
199 return cstring("Exact");
200 case p4configv1::MatchField_MatchType_LPM:
201 return cstring("LPM");
202 case p4configv1::MatchField_MatchType_TERNARY:
203 return cstring("Ternary");
204 case p4configv1::MatchField_MatchType_RANGE:
205 return cstring("Range");
206 case p4configv1::MatchField_MatchType_OPTIONAL:
207 return cstring("Optional");
208 default:
209 return std::nullopt;
210 }
211}
212
213static inline std::optional<cstring> transformOtherMatchType(std::string matchType) {
214 if (matchType == "atcam_partition_index")
215 return cstring("ATCAM");
216 else if (matchType == "dleft_hash")
217 return cstring("DLEFT_HASH");
218 else
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 ::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 suffix = "", P4Id idOffset = 1);
257
258 iterator begin() { return fields.begin(); }
259 const_iterator cbegin() { return fields.cbegin(); }
260 iterator end() { return fields.end(); }
261 const_iterator cend() { return fields.cend(); }
262 size_t size() { return fields.size(); }
263
264 private:
265 explicit TypeSpecParser(Fields &&fields) : fields(std::move(fields)) {}
266
267 Fields fields;
268};
269
271 public:
272 explicit BFRuntimeGenerator(const p4configv1::P4Info &p4info) : p4info(p4info) {}
273
275 virtual const Util::JsonObject *genSchema() const;
276
279 void serializeBFRuntimeSchema(std::ostream *destination);
280
281 protected:
282 // To avoid potential clashes with P4 names, we prefix the names of "fixed"
283 // data field with a '$'. For example, for TD_DATA_ACTION_MEMBER_ID, we
284 // use the name $ACTION_MEMBER_ID.
285 enum TDDataFieldIds : P4Id {
286 // ids for fixed data fields must not collide with the auto-generated
287 // ids for P4 fields (e.g. match key fields).
288 TD_DATA_START = (1 << 16),
289
290 TD_DATA_MATCH_PRIORITY,
291
292 TD_DATA_ACTION,
293 TD_DATA_ACTION_MEMBER_ID,
294 TD_DATA_SELECTOR_GROUP_ID,
295 TD_DATA_ACTION_MEMBER_STATUS,
296 TD_DATA_MAX_GROUP_SIZE,
297
298 TD_DATA_ENTRY_TTL,
299 TD_DATA_ENTRY_HIT_STATE,
300
301 TD_DATA_METER_SPEC_CIR_KBPS,
302 TD_DATA_METER_SPEC_PIR_KBPS,
303 TD_DATA_METER_SPEC_CBS_KBITS,
304 TD_DATA_METER_SPEC_PBS_KBITS,
305
306 TD_DATA_METER_SPEC_CIR_PPS,
307 TD_DATA_METER_SPEC_PIR_PPS,
308 TD_DATA_METER_SPEC_CBS_PKTS,
309 TD_DATA_METER_SPEC_PBS_PKTS,
310
311 TD_DATA_COUNTER_SPEC_BYTES,
312 TD_DATA_COUNTER_SPEC_PKTS,
313
314 TD_DATA_METER_INDEX,
315 TD_DATA_COUNTER_INDEX,
316 TD_DATA_REGISTER_INDEX,
317
318 TD_DATA_END,
319 };
320
322 struct Counter {
323 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2, BOTH = 3 };
324 std::string name;
325 P4Id id;
326 int64_t size;
327 Unit unit;
328 Util::JsonArray *annotations;
329
330 static std::optional<Counter> from(const p4configv1::Counter &counterInstance);
331 static std::optional<Counter> fromDirect(const p4configv1::DirectCounter &counterInstance);
332 };
333
335 struct Meter {
336 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2 };
337 enum Type { COLOR_UNAWARE = 0, COLOR_AWARE = 1 };
338 std::string name;
339 P4Id id;
340 int64_t size;
341 Unit unit;
342 Util::JsonArray *annotations;
343
344 static std::optional<Meter> from(const p4configv1::Meter &meterInstance);
345 static std::optional<Meter> fromDirect(const p4configv1::DirectMeter &meterInstance);
346 };
347
350 struct ActionProf {
351 std::string name;
352 P4Id id;
353 int64_t size;
354 std::vector<P4Id> tableIds;
355 Util::JsonArray *annotations;
356 static P4Id makeActProfId(P4Id implementationId);
357 static std::optional<ActionProf> from(const p4configv1::P4Info &p4info,
358 const p4configv1::ActionProfile &actionProfile);
359 };
360
362 struct Digest {
363 std::string name;
364 P4Id id;
365 p4configv1::P4DataTypeSpec typeSpec;
366 Util::JsonArray *annotations;
367
368 static std::optional<Digest> from(const p4configv1::Digest &digest);
369 };
370
372 struct Register {
373 std::string name;
374 std::string dataFieldName;
375 P4Id id;
376 int64_t size;
377 p4configv1::P4DataTypeSpec typeSpec;
378 Util::JsonArray *annotations;
379
380 static std::optional<Register> from(const p4configv1::Register &regInstance);
381 };
382
383 void addMatchTables(Util::JsonArray *tablesJson) const;
384 virtual bool addMatchTypePriority(std::optional<cstring> &matchType) const;
385 virtual void addConstTableAttr(Util::JsonArray *attrJson) const;
386 virtual void addActionProfs(Util::JsonArray *tablesJson) const;
387 virtual bool addActionProfIds(const p4configv1::Table &table,
388 Util::JsonObject *tableJson) const;
389 void addCounters(Util::JsonArray *tablesJson) const;
390 void addMeters(Util::JsonArray *tablesJson) const;
391 void addRegisters(Util::JsonArray *tablesJson) const;
392
393 void addCounterCommon(Util::JsonArray *tablesJson, const Counter &counter) const;
394 void addMeterCommon(Util::JsonArray *tablesJson, const Meter &meter) const;
395 void addRegisterCommon(Util::JsonArray *tablesJson, const Register &reg) const;
396 void addActionProfCommon(Util::JsonArray *tablesJson, const ActionProf &actionProf) const;
397 void addLearnFilters(Util::JsonArray *learnFiltersJson) const;
398 void addLearnFilterCommon(Util::JsonArray *learnFiltersJson, const Digest &digest) const;
399 virtual void addDirectResources(const p4configv1::Table &table, Util::JsonArray *dataJson,
400 Util::JsonArray *operationsJson,
401 Util::JsonArray *attributesJson,
402 P4Id maxActionParamId = 0) const;
403
404 virtual std::optional<bool> actProfHasSelector(P4Id actProfId) const;
410 Util::JsonArray *makeActionSpecs(const p4configv1::Table &table,
411 P4Id *maxActionParamId = nullptr) const;
412 virtual std::optional<Counter> getDirectCounter(P4Id counterId) const;
413 virtual std::optional<Meter> getDirectMeter(P4Id meterId) const;
414
424 const p4configv1::P4DataTypeSpec &typeSpec,
425 cstring instanceType, cstring instanceName,
426 const std::vector<cstring> *fieldNames = nullptr,
427 cstring prefix = "", cstring suffix = "",
428 P4Id idOffset = 1) const;
429
430 static void addMeterDataFields(Util::JsonArray *dataJson, const Meter &meter);
431 static Util::JsonObject *makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type,
432 bool repeated,
433 Util::JsonArray *annotations = nullptr);
434
435 static Util::JsonObject *makeContainerDataField(P4Id id, cstring name, Util::JsonArray *items,
436 bool repeated,
437 Util::JsonArray *annotations = nullptr);
438
439 static void addActionDataField(Util::JsonArray *dataJson, P4Id id, const std::string &name,
440 bool mandatory, bool read_only, Util::JsonObject *type,
441 Util::JsonArray *annotations = nullptr);
442
443 static void addKeyField(Util::JsonArray *dataJson, P4Id id, cstring name, bool mandatory,
444 cstring matchType, Util::JsonObject *type,
445 Util::JsonArray *annotations = nullptr);
446
447 static void addCounterDataFields(Util::JsonArray *dataJson, const Counter &counter);
448
449 static Util::JsonObject *initTableJson(const std::string &name, P4Id id, cstring tableType,
450 int64_t size, Util::JsonArray *annotations = nullptr);
451
452 static void addToDependsOn(Util::JsonObject *tableJson, P4Id id);
453
457 void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_,
458 P4Id idOffset = 1) const;
459
460 const p4configv1::P4Info &p4info;
461};
462
463} // namespace BFRT
464
465} // namespace P4
466
467#endif /* CONTROL_PLANE_BFRUNTIME_H_ */
Definition bfruntime.h:270
void transformTypeSpecToDataFields(Util::JsonArray *fieldsJson, const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType, cstring instanceName, const std::vector< cstring > *fieldNames=nullptr, cstring prefix="", cstring suffix="", P4Id idOffset=1) const
Definition bfruntime.cpp:397
void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_, P4Id idOffset=1) const
Definition bfruntime.cpp:411
void serializeBFRuntimeSchema(std::ostream *destination)
Definition bfruntime.cpp:871
virtual const Util::JsonObject * genSchema() const
Generates the schema as a Json object for the provided P4Info instance.
Definition bfruntime.cpp:850
Util::JsonArray * makeActionSpecs(const p4configv1::Table &table, P4Id *maxActionParamId=nullptr) const
Definition bfruntime.cpp:540
Definition bfruntime.h:240
Definition bfruntime.h:242
Definition json.h:111
Definition json.h:158
Definition json.h:50
Definition cstring.h:72
cstring escapeJson() const
Definition cstring.cpp:240
Definition applyOptionsPragmas.cpp:24
STL namespace.
Common counter representation between PSA and other architectures.
Definition bfruntime.h:322
Common digest representation between PSA and other architectures.
Definition bfruntime.h:362
Common meter representation between PSA and other architectures.
Definition bfruntime.h:335
Common register representation between PSA and other architectures.
Definition bfruntime.h:372
T * to() noexcept
Definition rtti.h:226