bmv2
Designing your own switch target with bmv2
header_unions.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_HEADER_UNIONS_H_
24 #define BM_BM_SIM_HEADER_UNIONS_H_
25 
26 #include <algorithm> // std::swap
27 #include <functional> // std::reference_wrapper
28 #include <string>
29 #include <utility>
30 #include <vector>
31 
32 #include "named_p4object.h"
33 #include "headers.h"
34 
35 namespace bm {
36 
37 using header_union_id_t = p4object_id_t;
38 
51 class HeaderUnion : public NamedP4Object {
52  public:
53  friend class PHV;
54 
55  HeaderUnion(const std::string &name, p4object_id_t id)
56  : NamedP4Object(name, id) { }
57 
58  void make_header_valid(size_t new_valid_idx) {
59  if (valid && valid_header_idx != new_valid_idx)
60  headers[valid_header_idx].get().mark_invalid();
61  valid_header_idx = new_valid_idx;
62  valid = true;
63  // the caller is responsible for making the new header valid
64  }
65 
66  void make_header_invalid(size_t idx) {
67  if (valid && valid_header_idx == idx) valid = false;
68  }
69 
70  // used for stacks of header unions
71  void swap_values(HeaderUnion *other) {
72  assert(headers.size() == other->headers.size());
73  std::swap(valid, other->valid);
74  std::swap(valid_header_idx, other->valid_header_idx);
75  // this is probably too conservative, I think we only need to swap valid
76  // headers, but this is a good place to start
77  for (size_t i = 0; i < headers.size(); i++)
78  headers[i].get().swap_values(&other->headers[i].get());
79  }
80 
84  return valid ? &headers[valid_header_idx].get() : nullptr;
85  }
86 
88  size_t get_num_headers() const { return headers.size(); }
89 
92  Header &at(size_t idx) { return headers.at(idx); }
94  const Header &at(size_t idx) const { return headers.at(idx); }
95 
96  // compare to another union instance; returns true iff both unions are valid,
97  // and the valid headers are the same in both unions.
98  bool cmp(const HeaderUnion &other) const;
99 
101  bool is_valid() const { return valid; }
102 
103  // no-ops on purpose
104  void mark_invalid() { }
105  void mark_valid() { }
106 
107  private:
108  // To be called by PHV class
109  // This is a special case, as I want to store a reference
110  // NOLINTNEXTLINE
111  void set_next_header(Header &h) {
112  headers.emplace_back(h);
113  }
114 
115  using HeaderRef = std::reference_wrapper<Header>;
116 
117  std::vector<HeaderRef> headers{};
118  bool valid{false};
119  size_t valid_header_idx{0};
120 };
121 
122 } // namespace bm
123 
124 #endif // BM_BM_SIM_HEADER_UNIONS_H_
bm::NamedP4Object
Definition: named_p4object.h:39
headers.h
bm::HeaderUnion::get_valid_header
Header * get_valid_header() const
Definition: header_unions.h:83
named_p4object.h
bm::HeaderUnion::at
Header & at(size_t idx)
Definition: header_unions.h:92
bm::HeaderUnion::get_num_headers
size_t get_num_headers() const
Returns the number of headers included in the union.
Definition: header_unions.h:88
bm::HeaderUnion::at
const Header & at(size_t idx) const
Definition: header_unions.h:94
bm::Header
Definition: headers.h:147
bm::HeaderUnion::is_valid
bool is_valid() const
Returns true if one of the headers in the union is valid.
Definition: header_unions.h:101
bm::PHV
Definition: phv.h:68
bm::HeaderUnion
Definition: header_unions.h:51