bmv2
Designing your own switch target with bmv2
packet.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_PACKET_H_
24 #define BM_BM_SIM_PACKET_H_
25 
26 #include <array>
27 #include <memory>
28 #include <mutex>
29 #include <chrono>
30 #include <string>
31 #include <vector>
32 #include <atomic>
33 #include <algorithm> // for std::min
34 #include <limits>
35 
36 #include <cassert>
37 
38 #include "device_id.h"
39 #include "packet_buffer.h"
40 #include "parser_error.h"
41 #include "phv_source.h"
42 #include "phv_forward.h"
43 
44 namespace bm {
45 
47 using packet_id_t = uint64_t;
48 
50 using copy_id_t = uint64_t;
51 
53 using port_t = uint32_t;
54 
55 class CopyIdGenerator {
56  private:
57  static constexpr size_t W = 4096;
58  struct Cntr {
59  // if default member initializer used, then g++-5 complains for some reason,
60  // so I had to provide an explicit constructor
61  // clang complains if 'noexcept' is missing
62  Cntr() noexcept : max(0), num(0) { }
63  uint16_t max;
64  uint16_t num;
65  };
66 
67  public:
68  copy_id_t add_one(packet_id_t packet_id);
69 
70  void remove_one(packet_id_t packet_id);
71 
72  copy_id_t get(packet_id_t packet_id);
73 
74  void reset(packet_id_t packet_id);
75 
76  private:
77  std::array<std::atomic<Cntr>, W> arr{{}};
78 };
79 
80 
98 class Packet final {
99  friend class SwitchWContexts;
100  friend class Switch;
101 
102  public:
103  using clock = std::chrono::system_clock;
104 
105  using buffer_state_t = PacketBuffer::state_t;
106 
108  static constexpr size_t nb_registers = 4u;
109 
110  static constexpr size_t INVALID_ENTRY_INDEX =
111  std::numeric_limits<size_t>::max();
112 
113  ~Packet();
114 
122  packet_id_t get_packet_id() const { return packet_id; }
123 
126  int get_egress_port() const { return egress_port; }
128  int get_ingress_port() const { return ingress_port; }
129 
131  void set_egress_port(int port) { egress_port = port; }
132  void set_ingress_port(int port) { ingress_port = port; }
133 
137  copy_id_t get_copy_id() const { return copy_id; }
138 
141  const std::string get_unique_id() const {
142  return std::to_string(packet_id) + "." + std::to_string(copy_id);
143  }
144 
145  void set_copy_id(copy_id_t id) { copy_id = id; }
146 
151  int get_ingress_length() const { return ingress_length; }
152 
156  void set_ingress_length(int length) { ingress_length = length; }
157 
158  void set_payload_size(size_t size) { payload_size = size; }
159 
160  size_t get_payload_size() const { return payload_size; }
161 
165  size_t get_data_size() const {
166  return std::min(buffer.get_data_size(), truncated_length);
167  }
168 
173  char *data() { return buffer.start(); }
174 
176  const char *data() const { return buffer.start(); }
177 
181  const buffer_state_t save_buffer_state() const {
182  return buffer.save_state();
183  }
184 
186  void restore_buffer_state(const buffer_state_t &state) {
187  buffer.restore_state(state);
188  }
189 
190  char *payload() {
191  assert(payload_size > 0);
192  return buffer.end() - payload_size;
193  }
194 
195  const char *payload() const {
196  assert(payload_size > 0);
197  return buffer.end() - payload_size;
198  }
199 
203  void truncate(size_t length) {
204  truncated_length = std::min(length, truncated_length);
205  }
206 
207  char *prepend(size_t bytes) { return buffer.push(bytes); }
208 
209  char *remove(size_t bytes) {
210  assert(buffer.get_data_size() >= payload_size + bytes);
211  return buffer.pop(bytes);
212  }
213 
215  uint64_t get_signature() const {
216  return signature;
217  }
218 
219  const PacketBuffer &get_packet_buffer() const { return buffer; }
220 
221  uint64_t get_ingress_ts_ms() const { return ingress_ts_ms; }
222 
223  // TODO(antonin): use references instead?
225  PHV *get_phv() { return phv.get(); }
227  const PHV *get_phv() const { return phv.get(); }
228 
230  void set_register(size_t idx, uint64_t v) { registers.at(idx) = v; }
232  uint64_t get_register(size_t idx) { return registers.at(idx); }
233 
234  void set_entry_index(size_t idx) { entry_index = idx; }
237  size_t get_entry_index() const { return entry_index; }
238 
239  void set_error_code(const ErrorCode &code) { error_code = code; }
243  ErrorCode get_error_code() const { return error_code; }
244 
245  void set_checksum_error(const bool b) { checksum_error = b; }
249  bool get_checksum_error() const { return checksum_error; }
250 
260  void mark_for_exit() { flags |= 1 << FLAGS_EXIT; }
263  void reset_exit() { flags &= ~(1 << FLAGS_EXIT); }
266  bool is_marked_for_exit() const { return flags & (1 << FLAGS_EXIT); }
267 
284  void change_context(cxt_id_t new_cxt);
285 
287  cxt_id_t get_context() const { return cxt_id; }
288 
289  // the *_ptr function are just here for convenience, the same can be achieved
290  // by the client by constructing a unique_ptr
291 
294  Packet clone_with_phv() const;
296  std::unique_ptr<Packet> clone_with_phv_ptr() const;
297 
302  std::unique_ptr<Packet> clone_with_phv_reset_metadata_ptr() const;
303 
307  Packet clone_no_phv() const;
309  std::unique_ptr<Packet> clone_no_phv_ptr() const;
310 
314  Packet clone_choose_context(cxt_id_t new_cxt) const;
316  std::unique_ptr<Packet> clone_choose_context_ptr(cxt_id_t new_cxt) const;
317 
319  Packet(const Packet &other) = delete;
321  Packet &operator=(const Packet &other) = delete;
322 
324  Packet(Packet &&other) noexcept;
326  Packet &operator=(Packet &&other) noexcept;
327 
328  // for tests
329  // TODO(antonin): find a better solution, no-one is supposed to use these
330  static Packet make_new(PHVSourceIface *phv_source);
331  // cpplint false positive
332  // NOLINTNEXTLINE(whitespace/operators)
333  static Packet make_new(int ingress_length, PacketBuffer &&buffer,
334  PHVSourceIface *phv_source);
335  static Packet make_new(cxt_id_t cxt, port_t ingress_port, packet_id_t id,
336  copy_id_t copy_id, int ingress_length,
337  // cpplint false positive
338  // NOLINTNEXTLINE(whitespace/operators)
339  PacketBuffer &&buffer, PHVSourceIface *phv_source);
340 
341  private:
342  Packet(cxt_id_t cxt_id, port_t ingress_port, packet_id_t id,
343  copy_id_t copy_id, int ingress_length, PacketBuffer &&buffer,
344  PHVSourceIface *phv_source);
345 
346  void update_signature(uint64_t seed = 0);
347  void set_ingress_ts();
348 
349  cxt_id_t cxt_id{0};
350  port_t ingress_port{0};
351  port_t egress_port{0};
352  packet_id_t packet_id{0};
353  copy_id_t copy_id{0};
354  int ingress_length{0};
355 
356  enum PacketFlags {
357  FLAGS_EXIT = 0
358  };
359  int flags{0};
360 
361  uint64_t signature{0};
362 
363  PacketBuffer buffer{};
364 
365  size_t payload_size{0};
366 
367  size_t truncated_length{std::numeric_limits<size_t>::max()};
368 
369  clock::time_point ingress_ts{};
370  uint64_t ingress_ts_ms{};
371 
372  std::unique_ptr<PHV> phv;
373 
374  PHVSourceIface *phv_source{nullptr};
375 
376  // General purpose registers available to a target, they can be written with
377  // Packet::set_register and read with Packet::get_register
378  std::array<uint64_t, nb_registers> registers;
379 
380  // Used to store the index of the entry returned by the last match table
381  // lookup; INVALID_ENTRY_INDEX if lookup was a miss.
382  size_t entry_index{INVALID_ENTRY_INDEX};
383 
384  ErrorCode error_code{ErrorCode::make_invalid()};
385 
386  bool checksum_error{false};
387 
388  private:
389  static CopyIdGenerator *copy_id_gen;
390 };
391 
392 } // namespace bm
393 
394 #endif // BM_BM_SIM_PACKET_H_
bm::Packet::set_register
void set_register(size_t idx, uint64_t v)
Write to general purpose register at index idx.
Definition: packet.h:230
bm::Switch
Definition: switch.h:973
bm::Packet::clone_with_phv_reset_metadata_ptr
std::unique_ptr< Packet > clone_with_phv_reset_metadata_ptr() const
bm::Packet::set_ingress_length
void set_ingress_length(int length)
Definition: packet.h:156
bm::Packet::get_context
cxt_id_t get_context() const
Returns the id of the Context this packet currently belongs to.
Definition: packet.h:287
bm::Packet::get_signature
uint64_t get_signature() const
Get a 64-bit hash of the incoming packet data.
Definition: packet.h:215
bm::Packet::get_entry_index
size_t get_entry_index() const
Definition: packet.h:237
bm::Packet::clone_with_phv_ptr
std::unique_ptr< Packet > clone_with_phv_ptr() const
bm::copy_id_t
uint64_t copy_id_t
Integral type used to distinguish between different clones of a packet.
Definition: packet.h:50
bm::Packet::is_marked_for_exit
bool is_marked_for_exit() const
Definition: packet.h:266
bm::Packet::get_phv
PHV * get_phv()
Get a pointer to the packet's phv.
Definition: packet.h:225
bm::Packet::clone_with_phv_reset_metadata
Packet clone_with_phv_reset_metadata() const
bm::Packet::data
char * data()
Definition: packet.h:173
bm::Packet::get_error_code
ErrorCode get_error_code() const
Definition: packet.h:243
bm::SwitchWContexts
Definition: switch.h:100
bm::Packet::get_ingress_port
int get_ingress_port() const
Get the ingress_port of the packet.
Definition: packet.h:128
bm::Packet::get_phv
const PHV * get_phv() const
Get a pointer to the packet's phv.
Definition: packet.h:227
bm::Packet::get_data_size
size_t get_data_size() const
Definition: packet.h:165
bm::port_t
uint32_t port_t
Integral type used to identify a given port.
Definition: packet.h:53
bm::Packet::truncate
void truncate(size_t length)
Definition: packet.h:203
bm::ErrorCode::make_invalid
static ErrorCode make_invalid()
Definition: parser_error.h:57
bm::packet_id_t
uint64_t packet_id_t
Integral type used to identify a given data packet.
Definition: packet.h:47
bm::Packet
Definition: packet.h:98
bm::Packet::change_context
void change_context(cxt_id_t new_cxt)
bm::Packet::save_buffer_state
const buffer_state_t save_buffer_state() const
Definition: packet.h:181
bm::ErrorCode
Definition: parser_error.h:35
bm::Packet::get_packet_id
packet_id_t get_packet_id() const
Definition: packet.h:122
bm::Packet::get_copy_id
copy_id_t get_copy_id() const
Definition: packet.h:137
bm::Packet::get_unique_id
const std::string get_unique_id() const
Definition: packet.h:141
bm::Packet::get_checksum_error
bool get_checksum_error() const
Definition: packet.h:249
bm::Packet::clone_no_phv
Packet clone_no_phv() const
bm::Packet::operator=
Packet & operator=(const Packet &other)=delete
Deleted copy assignment operator.
bm::Packet::Packet
Packet(const Packet &other)=delete
Deleted copy constructor.
bm::Packet::clone_choose_context
Packet clone_choose_context(cxt_id_t new_cxt) const
bm::Packet::get_egress_port
int get_egress_port() const
Definition: packet.h:126
bm::Packet::reset_exit
void reset_exit()
Definition: packet.h:263
parser_error.h
bm::Packet::clone_with_phv
Packet clone_with_phv() const
bm::PacketBuffer
Definition: packet_buffer.h:48
bm::Packet::get_ingress_length
int get_ingress_length() const
Definition: packet.h:151
bm::Packet::nb_registers
static constexpr size_t nb_registers
Number of general purpose registers per packet.
Definition: packet.h:108
bm::Packet::data
const char * data() const
Definition: packet.h:176
bm::Packet::mark_for_exit
void mark_for_exit()
Definition: packet.h:260
bm::Packet::clone_no_phv_ptr
std::unique_ptr< Packet > clone_no_phv_ptr() const
bm::Packet::clone_choose_context_ptr
std::unique_ptr< Packet > clone_choose_context_ptr(cxt_id_t new_cxt) const
bm::Packet::restore_buffer_state
void restore_buffer_state(const buffer_state_t &state)
See save_buffer_state()
Definition: packet.h:186
bm::PHV
Definition: phv.h:68
bm::Packet::set_egress_port
void set_egress_port(int port)
Set the egress_port of the packet, which is the target responsibility.
Definition: packet.h:131
bm::Packet::get_register
uint64_t get_register(size_t idx)
Read general purpose register at index idx.
Definition: packet.h:232
packet_buffer.h