bmv2
Designing your own switch target with bmv2
fields.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_FIELDS_H_
24 #define BM_BM_SIM_FIELDS_H_
25 
26 #include <bm/config.h>
27 
28 #include <algorithm> // for std::copy
29 
30 #include <cassert>
31 
32 #include "data.h"
33 #include "bytecontainer.h"
34 #include "bignum.h"
35 #include "debugger.h"
36 
37 namespace bm {
38 
39 class Header;
40 
46 class Field : public Data {
47  public:
48  // Data() is called automatically
49  // I wanted to have a separate class for signed fields, inheriting from
50  // Field. Unfortunately that would require adding an extra level of
51  // indirection in Header (for the field vector), so I am sticking to this for
52  // now.
53  explicit Field(int nbits, Header *parent_hdr, bool arith_flag = true,
54  bool is_signed = false, bool hidden = false, bool VL = false,
55  bool is_saturating = false);
56 
57  // to avoid dynamic resizing of the Bytecontainer, which would invalide field
58  // references
59  void reserve_VL(size_t max_bytes);
60 
61  // Overload set? Make it more generic (arbitary length) ?
62  // It is probably only going to be used by the checksum engine anyway...
63  void set_bytes(const char *src_bytes, int len) {
64  assert(len == nbytes);
65  std::copy(src_bytes, src_bytes + len, bytes.begin());
66  if (arith) sync_value();
67  }
68 
69  void sync_value() {
70  bignum::import_bytes(&value, bytes.data(), nbytes);
71  if (is_signed && bignum::test_bit(value, nbits - 1)) {
72  bignum::clear_bit(&value, nbits - 1);
73  value += min;
74  }
75  written_to = true;
76  // TODO(antonin): should notifications be disabled for hidden fields?
77  DEBUGGER_NOTIFY_UPDATE(*packet_id, my_id, bytes.data(), nbits);
78  }
79 
83  const ByteContainer &get_bytes() const {
84  return bytes;
85  }
86 
90  int get_nbytes() const {
91  return nbytes;
92  }
93 
95  int get_nbits() const {
96  return nbits;
97  }
98 
99  void set_arith(bool arith_flag) { arith = arith_flag; }
100 
101  bool get_arith_flag() const { return arith; }
102 
103  void export_bytes() override {
104  std::fill(bytes.begin(), bytes.end(), 0); // very important !
105 
106  if (is_saturating) {
107  if (value < min) value = min;
108  else if (value > max) value = max;
109  }
110 
111  if (!is_signed) {
112  // is this efficient enough?
113  value &= mask;
114  bignum::export_bytes(bytes.data(), nbytes, value);
115  } else {
116  if (value < min || value > mask) {
117  value &= mask;
118  if (value > max) value -= (mask + 1);
119  }
120  if (value >= 0) {
121  bignum::export_bytes(bytes.data(), nbytes, value);
122  } else {
123  // e.g. if width is 8 and value is -127 (1000 0001), subtracting min
124  // (-128) one time gives us 1, a second time gives us 129, 129 has a
125  // bignum representation of 1000 0001, which is what we wanted
126  bignum::export_bytes(bytes.data(), nbytes, value - min - min);
127  }
128  }
129  written_to = true;
130  DEBUGGER_NOTIFY_UPDATE(*packet_id, my_id, bytes.data(), nbits);
131  }
132 
133  // useful for header stacks
134  void swap_values(Field *other);
135 
136  // returns the number of bits extracted
137  int extract(const char *data, int hdr_offset);
138 
139  int extract_VL(const char *data, int hdr_offset, int computed_nbits);
140 
141  // returns the number of bits deparsed
142  int deparse(char *data, int hdr_offset) const;
143 
144  void assign_VL(const Field &src);
145 
146  void reset_VL();
147 
148 #ifdef BM_DEBUG_ON
149  void set_id(uint64_t id) { my_id = id; }
150  void set_packet_id(const Debugger::PacketId *id) { packet_id = id; }
151 #else
152  void set_id(uint64_t) { }
153  void set_packet_id(const Debugger::PacketId *) { }
154 #endif
155 
156  // it's important to have a way of copying a field value without the packet_id
157  // pointer. This is used by PHV::copy_headers().
158  void copy_value(const Field &src);
159 
160  bool is_hidden() const {
161  return hidden;
162  }
163 
164  bool is_VL() const {
165  return VL;
166  }
167 
171  void set_written_to(bool v) {
172  written_to = v;
173  }
174 
177  bool get_written_to() const {
178  return written_to;
179  }
180 
181  private:
182  int nbits;
183  int nbytes;
184  ByteContainer bytes;
185  Header *parent_hdr;
186  bool is_signed{false};
187  bool hidden{false};
188  bool VL{false};
189  bool is_saturating{false};
190  bool written_to{false}; // used to keep track of whether a field was modified
191  Bignum mask{1};
192  Bignum max{1};
193  Bignum min{1};
194 #ifdef BM_DEBUG_ON
195  uint64_t my_id{};
196  const Debugger::PacketId *packet_id{&Debugger::dummy_PacketId};
197 #endif
198 };
199 
200 } // namespace bm
201 
202 #endif // BM_BM_SIM_FIELDS_H_
bm::Field::get_nbytes
int get_nbytes() const
Definition: fields.h:90
bytecontainer.h
bm::Field::get_nbits
int get_nbits() const
Get the number of bits occupied by this field in the packet header.
Definition: fields.h:95
bm::ByteContainer
Definition: bytecontainer.h:39
bm::Field::get_written_to
bool get_written_to() const
Definition: fields.h:177
bm::Field
Definition: fields.h:46
bm::ByteContainer::begin
iterator begin()
NC.
Definition: bytecontainer.h:125
bm::ByteContainer::data
char * data() noexcept
Definition: bytecontainer.h:223
bm::Field::set_written_to
void set_written_to(bool v)
Definition: fields.h:171
bm::Header
Definition: headers.h:147
bm::ByteContainer::end
iterator end()
NC.
Definition: bytecontainer.h:131
bm::Field::get_bytes
const ByteContainer & get_bytes() const
Definition: fields.h:83