P4C
The P4 Compiler
Loading...
Searching...
No Matches
backends/tofino/bf-p4c/control-plane/bfruntime.h
1
19#ifndef BACKENDS_TOFINO_BF_P4C_CONTROL_PLANE_BFRUNTIME_H_
20#define BACKENDS_TOFINO_BF_P4C_CONTROL_PLANE_BFRUNTIME_H_
21
22#include <algorithm>
23#include <iomanip>
24#include <iosfwd>
25#include <iterator>
26#include <limits>
27#include <optional>
28#include <ostream>
29#include <regex>
30#include <sstream>
31#include <string>
32
33#include "control-plane/p4RuntimeSerializer.h"
34#include "lib/big_int_util.h"
35#include "lib/error.h"
36#include "lib/exceptions.h"
37#include "lib/json.h"
38#include "lib/log.h"
39#include "lib/null.h"
40
41#pragma GCC diagnostic push
42#pragma GCC diagnostic ignored "-Wunused-parameter"
43#pragma GCC diagnostic ignored "-Wpedantic"
44#include "p4/config/v1/p4info.pb.h"
45#include "p4/config/v1/p4types.pb.h"
46#pragma GCC diagnostic pop
47
48using namespace P4;
49using namespace P4::literals;
50
51namespace p4configv1 = ::p4::config::v1;
52
53namespace P4 {
54struct P4RuntimeAPI;
55} // namespace P4
56
57namespace BFN {
58
59namespace BFRT {
60
61using P4Id = uint32_t;
62
63// Helpers
64template <typename T, typename R>
65static constexpr P4Id makeBFRuntimeId(T base, R prefix) {
66 return static_cast<P4Id>((base & 0xffffff) | (prefix << 24));
67}
68
69static constexpr P4Id getIdPrefix(P4Id id) { return ((id >> 24) & 0xff); }
70
71Util::JsonObject *findJsonTable(Util::JsonArray *tablesJson, cstring tblName);
72
73// See https://stackoverflow.com/a/33799784/4538702
74static std::string escapeJson(const std::string &s) {
75 std::ostringstream o;
76 for (char c : s) {
77 switch (c) {
78 case '"':
79 o << "\\\"";
80 break;
81 case '\\':
82 o << "\\\\";
83 break;
84 case '\b':
85 o << "\\b";
86 break;
87 case '\f':
88 o << "\\f";
89 break;
90 case '\n':
91 o << "\\n";
92 break;
93 case '\r':
94 o << "\\r";
95 break;
96 case '\t':
97 o << "\\t";
98 break;
99 default: {
100 if ('\x00' <= c && c <= '\x1f') {
101 o << "\\u" << std::hex << std::setw(4) << std::setfill('0')
102 << static_cast<int>(c);
103 } else {
104 o << c;
105 }
106 }
107 }
108 }
109 return o.str();
110}
111
112static Util::JsonObject *transformAnnotation(const std::string &annotation) {
113 auto *annotationJson = new Util::JsonObject();
114 // TODO: annotation string will need to be parsed so we can have it
115 // in key/value format here.
116 annotationJson->emplace("name"_cs, escapeJson(annotation));
117 return annotationJson;
118}
119
120template <typename It>
121static Util::JsonArray *transformAnnotations(const It &first, const It &last) {
122 auto *annotations = new Util::JsonArray();
123 for (auto it = first; it != last; it++) annotations->append(transformAnnotation(*it));
124 return annotations;
125}
126
127static Util::JsonArray *transformAnnotations(const p4configv1::Preamble &pre) {
128 return transformAnnotations(pre.annotations().begin(), pre.annotations().end());
129}
130
132template <typename T>
133static bool isOfType(P4Id id, T prefix) {
134 return getIdPrefix(id) == static_cast<P4Id>(prefix);
135}
136
137namespace Standard {
138
139template <typename It>
140static auto findP4InfoObject(const It &first, const It &last, P4Id objectId) -> const
141 typename std::iterator_traits<It>::value_type * {
142 using T = typename std::iterator_traits<It>::value_type;
143 auto desiredObject = std::find_if(
144 first, last, [&](const T &object) { return object.preamble().id() == objectId; });
145 if (desiredObject == last) return nullptr;
146 return &*desiredObject;
147}
148
149static const p4configv1::Table *findTable(const p4configv1::P4Info &p4info, P4Id tableId) {
150 const auto &tables = p4info.tables();
151 return findP4InfoObject(tables.begin(), tables.end(), tableId);
152}
153
154const p4configv1::ActionProfile *findActionProf(const p4configv1::P4Info &p4info,
155 P4Id actionProfId);
156
157const p4configv1::DirectCounter *findDirectCounter(const p4configv1::P4Info &p4info,
158 P4Id counterId);
159
160const p4configv1::DirectMeter *findDirectMeter(const p4configv1::P4Info &p4info, P4Id meterId);
161
162} // namespace Standard
163
164Util::JsonObject *makeTypeInt(cstring type, cstring mask = ""_cs);
165
166template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
167static Util::JsonObject *makeTypeInt(cstring type, T defaultValue, cstring mask = ""_cs) {
168 auto *typeObj = new Util::JsonObject();
169 typeObj->emplace("type"_cs, type);
170 typeObj->emplace("default_value"_cs, defaultValue);
171 if (!mask.isNullOrEmpty()) typeObj->emplace("mask"_cs, mask);
172 return typeObj;
173}
174
175Util::JsonObject *makeTypeBool(std::optional<bool> defaultValue = std::nullopt);
176
177Util::JsonObject *makeTypeBytes(int width, std::optional<int64_t> defaultValue = std::nullopt,
178 cstring mask = ""_cs);
179
180Util::JsonObject *makeTypeEnum(const std::vector<cstring> &choices,
181 std::optional<cstring> defaultValue = std::nullopt);
182
183void addSingleton(Util::JsonArray *dataJson, Util::JsonObject *dataField, bool mandatory,
184 bool readOnly);
185
186template <typename It>
187static std::vector<P4Id> collectTableIds(const p4configv1::P4Info &p4info, const It &first,
188 const It &last) {
189 std::vector<P4Id> tableIds;
190 for (auto it = first; it != last; it++) {
191 auto *table = Standard::findTable(p4info, *it);
192 if (table == nullptr) {
193 error("Invalid table id '%1%'", *it);
194 continue;
195 }
196 tableIds.push_back(*it);
197 }
198 return tableIds;
199}
200
205 public:
206 struct Field {
207 cstring name;
208 P4Id id;
209 Util::JsonObject *type;
210 };
211
212 using Fields = std::vector<Field>;
213 using iterator = Fields::iterator;
214 using const_iterator = Fields::const_iterator;
215
216 static TypeSpecParser make(const p4configv1::P4Info &p4info,
217 const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType,
218 cstring instanceName,
219 const std::vector<cstring> *fieldNames = nullptr,
220 cstring prefix = ""_cs, cstring suffix = ""_cs, P4Id idOffset = 1);
221
222 iterator begin() { return fields.begin(); }
223 const_iterator cbegin() { return fields.cbegin(); }
224 iterator end() { return fields.end(); }
225 const_iterator cend() { return fields.cend(); }
226
227 private:
228 explicit TypeSpecParser(Fields &&fields) : fields(std::move(fields)) {}
229
230 Fields fields;
231};
232
234 public:
235 explicit BFRuntimeGenerator(const p4configv1::P4Info &p4info) : p4info(p4info) {}
236
238 virtual const Util::JsonObject *genSchema() const;
239
242 void serializeBFRuntimeSchema(std::ostream *destination);
243
244 protected:
245 // To avoid potential clashes with P4 names, we prefix the names of "fixed"
246 // data field with a '$'. For example, for TD_DATA_ACTION_MEMBER_ID, we
247 // use the name $ACTION_MEMBER_ID.
248 enum TDDataFieldIds : P4Id {
249 // ids for fixed data fields must not collide with the auto-generated
250 // ids for P4 fields (e.g. match key fields).
251 TD_DATA_START = (1 << 16),
252
253 TD_DATA_MATCH_PRIORITY,
254
255 TD_DATA_ACTION,
256 TD_DATA_ACTION_MEMBER_ID,
257 TD_DATA_SELECTOR_GROUP_ID,
258 TD_DATA_ACTION_MEMBER_STATUS,
259 TD_DATA_MAX_GROUP_SIZE,
260
261 TD_DATA_ENTRY_TTL,
262 TD_DATA_ENTRY_HIT_STATE,
263
264 TD_DATA_METER_SPEC_CIR_KBPS,
265 TD_DATA_METER_SPEC_PIR_KBPS,
266 TD_DATA_METER_SPEC_CBS_KBITS,
267 TD_DATA_METER_SPEC_PBS_KBITS,
268
269 TD_DATA_METER_SPEC_CIR_PPS,
270 TD_DATA_METER_SPEC_PIR_PPS,
271 TD_DATA_METER_SPEC_CBS_PKTS,
272 TD_DATA_METER_SPEC_PBS_PKTS,
273
274 TD_DATA_COUNTER_SPEC_BYTES,
275 TD_DATA_COUNTER_SPEC_PKTS,
276
277 TD_DATA_METER_INDEX,
278 TD_DATA_COUNTER_INDEX,
279 TD_DATA_REGISTER_INDEX,
280
281 TD_DATA_END,
282 };
283
285 struct Counter {
286 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2, BOTH = 3 };
287 std::string name;
288 P4Id id;
289 int64_t size;
290 Unit unit;
291 Util::JsonArray *annotations;
292
293 static std::optional<Counter> from(const p4configv1::Counter &counterInstance);
294 static std::optional<Counter> fromDirect(const p4configv1::DirectCounter &counterInstance);
295 };
296
298 struct Meter {
299 enum Unit { UNSPECIFIED = 0, BYTES = 1, PACKETS = 2 };
300 enum Type { COLOR_UNAWARE = 0, COLOR_AWARE = 1 };
301 std::string name;
302 P4Id id;
303 int64_t size;
304 Unit unit;
305 Type type;
306 Util::JsonArray *annotations;
307
308 static std::optional<Meter> from(const p4configv1::Meter &meterInstance);
309 static std::optional<Meter> fromDirect(const p4configv1::DirectMeter &meterInstance);
310 };
311
314 struct ActionProf {
315 std::string name;
316 P4Id id;
317 int64_t size;
318 std::vector<P4Id> tableIds;
319 Util::JsonArray *annotations;
320 static P4Id makeActProfId(P4Id implementationId);
321 static std::optional<ActionProf> from(const p4configv1::P4Info &p4info,
322 const p4configv1::ActionProfile &actionProfile);
323 };
324
326 struct Digest {
327 std::string name;
328 P4Id id;
329 p4configv1::P4DataTypeSpec typeSpec;
330 Util::JsonArray *annotations;
331
332 static std::optional<Digest> from(const p4configv1::Digest &digest);
333 };
334
336 struct Register {
337 std::string name;
338 std::string dataFieldName;
339 P4Id id;
340 int64_t size;
341 p4configv1::P4DataTypeSpec typeSpec;
342 Util::JsonArray *annotations;
343
344 // static std::optional<Register>
345 // from(const p4configv1::ExternInstance& externInstance);
346 };
347
348 void addMatchTables(Util::JsonArray *tablesJson) const;
349 virtual void addActionProfs(Util::JsonArray *tablesJson) const;
350 virtual bool addActionProfIds(const p4configv1::Table &table,
351 Util::JsonObject *tableJson) const;
352 void addCounters(Util::JsonArray *tablesJson) const;
353 void addMeters(Util::JsonArray *tablesJson) const;
354
355 void addCounterCommon(Util::JsonArray *tablesJson, const Counter &counter) const;
356 void addMeterCommon(Util::JsonArray *tablesJson, const Meter &meter) const;
357 void addRegisterCommon(Util::JsonArray *tablesJson, const Register &meter) const;
358 void addActionProfCommon(Util::JsonArray *tablesJson, const ActionProf &actionProf) const;
359 void addLearnFilters(Util::JsonArray *learnFiltersJson) const;
360 void addLearnFilterCommon(Util::JsonArray *learnFiltersJson, const Digest &digest) const;
361 virtual void addDirectResources(const p4configv1::Table &table, Util::JsonArray *dataJson,
362 Util::JsonArray *operationsJson,
363 Util::JsonArray *attributesJson,
364 P4Id maxActionParamId = 0) const;
365
366 virtual std::optional<bool> actProfHasSelector(P4Id actProfId) const;
372 Util::JsonArray *makeActionSpecs(const p4configv1::Table &table,
373 P4Id *maxActionParamId = nullptr) const;
374 virtual std::optional<Counter> getDirectCounter(P4Id counterId) const;
375 virtual std::optional<Meter> getDirectMeter(P4Id meterId) const;
376
386 const p4configv1::P4DataTypeSpec &typeSpec,
387 cstring instanceType, cstring instanceName,
388 const std::vector<cstring> *fieldNames = nullptr,
389 cstring prefix = ""_cs, cstring suffix = ""_cs,
390 P4Id idOffset = 1) const;
391
392 static void addMeterDataFields(Util::JsonArray *dataJson, const Meter &meter);
393 static Util::JsonObject *makeCommonDataField(P4Id id, cstring name, Util::JsonObject *type,
394 bool repeated,
395 Util::JsonArray *annotations = nullptr);
396
397 static Util::JsonObject *makeContainerDataField(P4Id id, cstring name, Util::JsonArray *items,
398 bool repeated,
399 Util::JsonArray *annotations = nullptr);
400
401 static void addActionDataField(Util::JsonArray *dataJson, P4Id id, const std::string &name,
402 bool mandatory, bool read_only, Util::JsonObject *type,
403 Util::JsonArray *annotations = nullptr);
404
405 static void addKeyField(Util::JsonArray *dataJson, P4Id id, cstring name, bool mandatory,
406 cstring matchType, Util::JsonObject *type,
407 Util::JsonArray *annotations = nullptr);
408
409 static void addCounterDataFields(Util::JsonArray *dataJson, const Counter &counter);
410
411 static Util::JsonObject *initTableJson(const std::string &name, P4Id id, cstring tableType,
412 int64_t size, Util::JsonArray *annotations = nullptr);
413
414 static void addToDependsOn(Util::JsonObject *tableJson, P4Id id);
415
419 void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_,
420 P4Id idOffset = 1) const;
421
422 const p4configv1::P4Info &p4info;
423};
424
425} // namespace BFRT
426} // namespace BFN
427
428#endif /* BACKENDS_TOFINO_BF_P4C_CONTROL_PLANE_BFRUNTIME_H_ */
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:233
Util::JsonArray * makeActionSpecs(const p4configv1::Table &table, P4Id *maxActionParamId=nullptr) const
Definition backends/tofino/bf-p4c/control-plane/bfruntime.cpp:661
virtual const Util::JsonObject * genSchema() const
Generates the schema as a Json object for the provided P4Info instance.
Definition backends/tofino/bf-p4c/control-plane/bfruntime.cpp:967
void transformTypeSpecToDataFields(Util::JsonArray *fieldsJson, const p4configv1::P4DataTypeSpec &typeSpec, cstring instanceType, cstring instanceName, const std::vector< cstring > *fieldNames=nullptr, cstring prefix=""_cs, cstring suffix=""_cs, P4Id idOffset=1) const
Definition backends/tofino/bf-p4c/control-plane/bfruntime.cpp:498
void serializeBFRuntimeSchema(std::ostream *destination)
Definition backends/tofino/bf-p4c/control-plane/bfruntime.cpp:988
void addRegisterDataFields(Util::JsonArray *dataJson, const Register &register_, P4Id idOffset=1) const
Definition backends/tofino/bf-p4c/control-plane/bfruntime.cpp:512
Common register representation between PSA and other architectures.
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:336
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:204
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:206
Definition json.h:115
Definition json.h:164
Definition cstring.h:85
The namespace encapsulating Barefoot/Intel-specific stuff.
Definition add_t2na_meta.cpp:21
Definition cstring.h:80
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 backends/tofino/bf-p4c/control-plane/bfruntime.h:314
Common counter representation between PSA and other architectures.
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:285
Common digest representation between PSA and other architectures.
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:326
Common meter representation between PSA and other architectures.
Definition backends/tofino/bf-p4c/control-plane/bfruntime.h:298
Definition p4RuntimeSerializer.h:57