bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
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
44namespace bm {
45
47using packet_id_t = uint64_t;
48
50using copy_id_t = uint64_t;
51
53using port_t = uint32_t;
54
55class 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
98class 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
296 std::unique_ptr<Packet> clone_with_phv_ptr() const;
297
302 std::unique_ptr<Packet> clone_with_phv_reset_metadata_ptr() const;
303
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_
Definition parser_error.h:35
static ErrorCode make_invalid()
Definition parser_error.h:57
Definition phv.h:68
Definition packet_buffer.h:48
Definition packet.h:98
size_t get_entry_index() const
Definition packet.h:237
int get_ingress_port() const
Get the ingress_port of the packet.
Definition packet.h:128
void set_register(size_t idx, uint64_t v)
Write to general purpose register at index idx.
Definition packet.h:230
void restore_buffer_state(const buffer_state_t &state)
See save_buffer_state()
Definition packet.h:186
void truncate(size_t length)
Definition packet.h:203
int get_egress_port() const
Definition packet.h:126
Packet & operator=(Packet &&other) noexcept
Move assignment operator.
std::unique_ptr< Packet > clone_with_phv_reset_metadata_ptr() const
const char * data() const
Definition packet.h:176
void set_egress_port(int port)
Set the egress_port of the packet, which is the target responsibility.
Definition packet.h:131
size_t get_data_size() const
Definition packet.h:165
bool is_marked_for_exit() const
Definition packet.h:266
Packet(Packet &&other) noexcept
Move constructor.
packet_id_t get_packet_id() const
Definition packet.h:122
bool get_checksum_error() const
Definition packet.h:249
void mark_for_exit()
Definition packet.h:260
std::unique_ptr< Packet > clone_no_phv_ptr() const
Packet clone_with_phv_reset_metadata() const
Packet clone_no_phv() const
int get_ingress_length() const
Definition packet.h:151
const PHV * get_phv() const
Get a pointer to the packet's phv.
Definition packet.h:227
PHV * get_phv()
Get a pointer to the packet's phv.
Definition packet.h:225
Packet(const Packet &other)=delete
Deleted copy constructor.
char * data()
Definition packet.h:173
Packet & operator=(const Packet &other)=delete
Deleted copy assignment operator.
uint64_t get_register(size_t idx)
Read general purpose register at index idx.
Definition packet.h:232
ErrorCode get_error_code() const
Definition packet.h:243
const std::string get_unique_id() const
Definition packet.h:141
static constexpr size_t nb_registers
Number of general purpose registers per packet.
Definition packet.h:108
copy_id_t get_copy_id() const
Definition packet.h:137
std::unique_ptr< Packet > clone_with_phv_ptr() const
void reset_exit()
Definition packet.h:263
Packet clone_with_phv() const
void set_ingress_length(int length)
Definition packet.h:156
Packet clone_choose_context(cxt_id_t new_cxt) const
std::unique_ptr< Packet > clone_choose_context_ptr(cxt_id_t new_cxt) const
cxt_id_t get_context() const
Returns the id of the Context this packet currently belongs to.
Definition packet.h:287
uint64_t get_signature() const
Get a 64-bit hash of the incoming packet data.
Definition packet.h:215
const buffer_state_t save_buffer_state() const
Definition packet.h:181
void change_context(cxt_id_t new_cxt)
Definition switch.h:100
Definition switch.h:973
uint64_t copy_id_t
Integral type used to distinguish between different clones of a packet.
Definition packet.h:50
uint32_t port_t
Integral type used to identify a given port.
Definition packet.h:53
uint64_t packet_id_t
Integral type used to identify a given data packet.
Definition packet.h:47