bmv2
Designing your own switch target with bmv2
phv.h
Go to the documentation of this file.
1 /* Copyright 2013-present Barefoot Networks, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 /*
17  * Antonin Bas (antonin@barefootnetworks.com)
18  *
19  */
20 
22 
23 #ifndef BM_BM_SIM_PHV_H_
24 #define BM_BM_SIM_PHV_H_
25 
26 #include <vector>
27 #include <unordered_map>
28 #include <string>
29 #include <functional>
30 #include <set>
31 #include <unordered_set>
32 #include <map>
33 #include <memory>
34 
35 #include <cassert>
36 
37 #include "fields.h"
38 #include "headers.h"
39 #include "header_unions.h"
40 #include "stacks.h"
41 #include "named_p4object.h"
42 #include "expressions.h"
43 
44 namespace bm {
45 
46 using header_id_t = p4object_id_t;
47 
48 // forward declaration
49 class PHVFactory;
50 
68 class PHV {
69  using HeaderRef = std::reference_wrapper<Header>;
70  using FieldRef = std::reference_wrapper<Field>;
71 
72  public:
73  friend class PHVFactory;
74  friend class Packet;
75 
76  using HeaderNamesMap = std::unordered_map<std::string, HeaderRef>;
79  using header_name_iterator = HeaderNamesMap::iterator;
81  using const_header_name_iterator = HeaderNamesMap::const_iterator;
82 
83  using FieldNamesMap = std::unordered_map<std::string, FieldRef>;
84 
86  using header_iterator = std::vector<Header>::iterator;
88  using const_header_iterator = std::vector<Header>::const_iterator;
89 
90  public:
91  PHV() {}
92 
93  PHV(size_t num_headers, size_t num_header_stacks,
94  size_t num_header_unions, size_t num_header_union_stacks);
95 
97  Header &get_header(header_id_t header_index) {
98  return headers[header_index];
99  }
100 
102  const Header &get_header(header_id_t header_index) const {
103  return headers[header_index];
104  }
105 
109  Header &get_header(const std::string &header_name) {
110  return headers_map.at(header_name);
111  }
112 
114  const Header &get_header(const std::string &header_name) const {
115  return headers_map.at(header_name);
116  }
117 
119  bool has_header(const std::string &header_name) const {
120  auto it = headers_map.find(header_name);
121  return (it != headers_map.end());
122  }
123 
128  Field &get_field(header_id_t header_index, int field_offset) {
129  return headers[header_index].get_field(field_offset);
130  }
131 
133  const Field &get_field(header_id_t header_index, int field_offset) const {
134  return headers[header_index].get_field(field_offset);
135  }
136 
140  Field &get_field(const std::string &field_name) {
141  return fields_map.at(field_name);
142  }
143 
145  const Field &get_field(const std::string &field_name) const {
146  return fields_map.at(field_name);
147  }
148 
151  bool has_field(const std::string &field_name) const {
152  auto it = fields_map.find(field_name);
153  return (it != fields_map.end());
154  }
155 
158  HeaderStack &get_header_stack(header_stack_id_t header_stack_index) {
159  return header_stacks[header_stack_index];
160  }
161 
164  header_stack_id_t header_stack_index) const {
165  return header_stacks[header_stack_index];
166  }
167 
170  HeaderUnion &get_header_union(header_union_id_t header_union_index) {
171  return header_unions[header_union_index];
172  }
173 
176  header_union_id_t header_union_index) const {
177  return header_unions[header_union_index];
178  }
179 
183  header_union_stack_id_t header_union_stack_index) {
184  return header_union_stacks[header_union_stack_index];
185  }
186 
190  header_union_stack_id_t header_union_stack_index) const {
191  return header_union_stacks[header_union_stack_index];
192  }
193 
195  void reset();
196 
199  void reset_header_stacks();
200 
204  void reset_metadata();
205 
207  void reset_headers();
208 
213  void set_written_to(bool written_to_value);
214 
216  PHV(const PHV &other) = delete;
218  PHV &operator=(const PHV &other) = delete;
219 
221  PHV(PHV &&other) = default;
223  PHV &operator=(PHV &&other) = default;
224 
232  void copy_headers(const PHV &src);
233 
234  void set_packet_id(const uint64_t id1, const uint64_t id2) {
235  packet_id = {id1, id2};
236  }
237 
238  // iterators
239 
248  return headers_map.begin();
249  }
250 
253  return headers_map.begin();
254  }
255 
259  return headers_map.end();
260  }
261 
264  return headers_map.end();
265  }
266 
272  header_iterator header_begin() { return headers.begin(); }
273 
275  const_header_iterator header_begin() const { return headers.begin(); }
276 
278  header_iterator header_end() { return headers.end(); }
279 
281  const_header_iterator header_end() const { return headers.end(); }
282 
284  size_t num_headers() const { return headers.size(); }
285 
288  const std::string get_field_name(header_id_t header_index,
289  int field_offset) const;
290 
291  private:
292  // To be used only by PHVFactory
293  // all headers need to be pushed back in order (according to header_index) !!!
294  // TODO(antonin): remove this constraint?
295  void push_back_header(const std::string &header_name,
296  header_id_t header_index,
297  const HeaderType &header_type,
298  const std::set<int> &arith_offsets,
299  const bool metadata);
300 
301  void push_back_header_stack(const std::string &header_stack_name,
302  header_stack_id_t header_stack_index,
303  const HeaderType &header_type,
304  const std::vector<header_id_t> &header_ids);
305 
306  void push_back_header_union(const std::string &header_union_name,
307  header_union_id_t header_union_index,
308  const std::vector<header_id_t> &header_ids);
309 
310  void push_back_header_union_stack(
311  const std::string &header_union_stack_name,
312  header_union_stack_id_t header_union_stack_index,
313  const std::vector<header_union_id_t> &header_union_ids);
314 
315  // get_field(from) will be equivalent to get_field(to)
316  // 'to' needs to be a valid field name (or a previously inserted alias)
317  // 'from' (the alias) does not need to adhere to the "hdr.f" naming convention
318  void add_field_alias(const std::string &from, const std::string &to);
319 
320  private:
321  std::vector<Header> headers{};
322  std::vector<HeaderStack> header_stacks{};
323  std::vector<HeaderUnion> header_unions{};
324  std::vector<HeaderUnionStack> header_union_stacks{};
325  HeaderNamesMap headers_map{};
326  FieldNamesMap fields_map{};
327  size_t capacity{0};
328  size_t capacity_stacks{0};
329  size_t capacity_unions{0};
330  size_t capacity_union_stacks{0};
331  Debugger::PacketId packet_id;
332 };
333 
334 class PHVFactory {
335  private:
336  struct HeaderDesc {
337  const std::string name;
338  header_id_t index;
339  const HeaderType &header_type;
340  std::set<int> arith_offsets{};
341  bool metadata;
342 
343  HeaderDesc(const std::string &name, const header_id_t index,
344  const HeaderType &header_type, const bool metadata)
345  : name(name), index(index), header_type(header_type),
346  metadata(metadata) {
347  for (int offset = 0; offset < header_type.get_num_fields(); offset++) {
348  arith_offsets.insert(offset);
349  }
350  }
351  };
352 
353  struct HeaderStackDesc {
354  const std::string name;
355  header_stack_id_t index;
356  const HeaderType &header_type;
357  std::vector<header_id_t> headers;
358 
359  HeaderStackDesc(const std::string &name, const header_stack_id_t index,
360  const HeaderType &header_type,
361  const std::vector<header_id_t> &headers)
362  : name(name), index(index), header_type(header_type),
363  headers(headers) { }
364  };
365 
366  struct HeaderUnionDesc {
367  const std::string name;
368  header_union_id_t index;
369  std::vector<header_id_t> headers;
370 
371  HeaderUnionDesc(const std::string &name, const header_union_id_t index,
372  const std::vector<header_id_t> &headers)
373  : name(name), index(index), headers(headers) { }
374  };
375 
376  struct HeaderUnionStackDesc {
377  const std::string name;
378  header_union_stack_id_t index;
379  std::vector<header_union_id_t> header_unions;
380 
381  HeaderUnionStackDesc(const std::string &name,
382  const header_union_stack_id_t index,
383  const std::vector<header_union_id_t> &header_unions)
384  : name(name), index(index), header_unions(header_unions) { }
385  };
386 
387  public:
388  void push_back_header(const std::string &header_name,
389  const header_id_t header_index,
390  const HeaderType &header_type,
391  const bool metadata = false);
392 
393  void push_back_header_stack(const std::string &header_stack_name,
394  const header_stack_id_t header_stack_index,
395  const HeaderType &header_type,
396  const std::vector<header_id_t> &headers);
397 
398  void push_back_header_union(const std::string &header_union_name,
399  const header_stack_id_t header_union_index,
400  const std::vector<header_id_t> &headers);
401 
402  void push_back_header_union_stack(
403  const std::string &header_union_stack_name,
404  const header_union_stack_id_t header_union_stack_index,
405  const std::vector<header_union_id_t> &header_unions);
406 
407  void add_field_alias(const std::string &from, const std::string &to);
408 
409  const HeaderType &get_header_type(header_id_t header_id) const {
410  return header_descs.at(header_id).header_type;
411  }
412 
413  const HeaderType &get_header_stack_type(
414  header_stack_id_t header_stack_id) const {
415  return header_stack_descs.at(header_stack_id).header_type;
416  }
417 
418  void enable_field_arith(header_id_t header_id, int field_offset);
419 
420  void enable_all_field_arith(header_id_t header_id);
421 
422  void disable_field_arith(header_id_t header_id, int field_offset);
423 
424  void disable_all_field_arith(header_id_t header_id);
425 
426  void enable_stack_field_arith(header_stack_id_t header_stack_id,
427  int field_offset);
428 
429  void enable_all_stack_field_arith(header_stack_id_t header_stack_id);
430 
431  void enable_union_stack_field_arith(
432  header_union_stack_id_t header_union_stack_id, size_t header_offset,
433  int field_offset);
434 
435  void enable_all_union_stack_field_arith(
436  header_union_stack_id_t header_union_stack_id, size_t header_offset);
437 
438  void enable_all_union_stack_field_arith(
439  header_union_stack_id_t header_union_stack_id);
440 
441  void enable_all_arith();
442 
443  std::unique_ptr<PHV> create() const;
444 
445  private:
446  std::map<header_id_t, HeaderDesc> header_descs{}; // sorted by header id
447  std::map<header_stack_id_t, HeaderStackDesc> header_stack_descs{};
448  std::map<header_union_id_t, HeaderUnionDesc> header_union_descs{};
449  std::map<header_union_stack_id_t, HeaderUnionStackDesc>
450  header_union_stack_descs{};
451  std::map<std::string, std::string> field_aliases{}; // order does not matter
452  std::unordered_set<std::string> field_names{}; // just for debugging
453 };
454 
455 } // namespace bm
456 
457 #endif // BM_BM_SIM_PHV_H_
bm::PHV::get_header
const Header & get_header(const std::string &header_name) const
Definition: phv.h:114
bm::PHV::const_header_name_iterator
HeaderNamesMap::const_iterator const_header_name_iterator
Definition: phv.h:81
bm::PHV::set_written_to
void set_written_to(bool written_to_value)
bm::PHV::get_header_union_stack
const HeaderUnionStack & get_header_union_stack(header_union_stack_id_t header_union_stack_index) const
Definition: phv.h:189
bm::PHV::const_header_iterator
std::vector< Header >::const_iterator const_header_iterator
Used to iterate over headers in ascending id order.
Definition: phv.h:88
bm::PHV::get_header_union
const HeaderUnion & get_header_union(header_union_id_t header_union_index) const
Definition: phv.h:175
bm::PHV::get_header_union
HeaderUnion & get_header_union(header_union_id_t header_union_index)
Definition: phv.h:170
bm::PHV::header_begin
const_header_iterator header_begin() const
Definition: phv.h:275
header_unions.h
headers.h
bm::PHV::header_name_begin
const_header_name_iterator header_name_begin() const
Definition: phv.h:252
bm::PHV::has_header
bool has_header(const std::string &header_name) const
Returns true if there exists a Header with name header_name in this PHV.
Definition: phv.h:119
bm::PHV::header_end
header_iterator header_end()
Returns an iterator to the last element in the PHV. See header_begin().
Definition: phv.h:278
bm::PHV::header_name_end
header_name_iterator header_name_end()
Definition: phv.h:258
bm::PHV::num_headers
size_t num_headers() const
Returns the number of headers included in the PHV.
Definition: phv.h:284
named_p4object.h
bm::PHV::get_header_union_stack
HeaderUnionStack & get_header_union_stack(header_union_stack_id_t header_union_stack_index)
Definition: phv.h:182
bm::Packet
Definition: packet.h:98
bm::PHV::header_name_begin
header_name_iterator header_name_begin()
Definition: phv.h:247
bm::PHV::reset_headers
void reset_headers()
Reset all header fields to 0.
bm::Field
Definition: fields.h:46
bm::PHV::get_header_stack
HeaderStack & get_header_stack(header_stack_id_t header_stack_index)
Definition: phv.h:158
bm::PHV::reset_metadata
void reset_metadata()
bm::HeaderStack
detail::MyStack< Header > HeaderStack
Definition: stacks.h:212
bm::PHV::get_header_stack
const HeaderStack & get_header_stack(header_stack_id_t header_stack_index) const
Definition: phv.h:163
bm::PHV::get_header
Header & get_header(header_id_t header_index)
Access the Header with id header_index, with no bound checking.
Definition: phv.h:97
bm::PHV::header_begin
header_iterator header_begin()
Definition: phv.h:272
bm::PHV::copy_headers
void copy_headers(const PHV &src)
bm::PHV::get_header
const Header & get_header(header_id_t header_index) const
Access the Header with id header_index, with no bound checking.
Definition: phv.h:102
bm::PHV::header_name_end
const_header_name_iterator header_name_end() const
Definition: phv.h:263
fields.h
bm::PHV::get_field
const Field & get_field(const std::string &field_name) const
Definition: phv.h:145
bm::PHV::get_field
const Field & get_field(header_id_t header_index, int field_offset) const
Definition: phv.h:133
bm::PHV::get_field
Field & get_field(const std::string &field_name)
Definition: phv.h:140
bm::PHV::get_header
Header & get_header(const std::string &header_name)
Definition: phv.h:109
bm::PHV::operator=
PHV & operator=(const PHV &other)=delete
Deleted copy assignment operator.
bm::PHV::has_field
bool has_field(const std::string &field_name) const
Definition: phv.h:151
bm::PHV::get_field_name
const std::string get_field_name(header_id_t header_index, int field_offset) const
bm::Header
Definition: headers.h:147
bm::HeaderUnionStack
detail::MyStack< HeaderUnion > HeaderUnionStack
Definition: stacks.h:223
bm::PHV::reset_header_stacks
void reset_header_stacks()
stacks.h
bm::PHV
Definition: phv.h:68
bm::PHV::header_end
const_header_iterator header_end() const
Returns an iterator to the last element in the PHV. See header_begin().
Definition: phv.h:281
bm::PHV::get_field
Field & get_field(header_id_t header_index, int field_offset)
Definition: phv.h:128
bm::PHV::header_name_iterator
HeaderNamesMap::iterator header_name_iterator
Definition: phv.h:79
bm::HeaderUnion
Definition: header_unions.h:51
bm::PHV::reset
void reset()
Mark all Header instances in the PHV as invalid.
bm::PHV::header_iterator
std::vector< Header >::iterator header_iterator
Used to iterate over headers in ascending id order.
Definition: phv.h:86