23 #ifndef BM_BM_SIM_PARSER_H_
24 #define BM_BM_SIM_PARSER_H_
29 #include <type_traits>
35 #include "phv_forward.h"
45 class ArithExpression;
54 static field_t make(header_id_t header,
int offset) {
55 field_t field = {header, offset};
60 struct ParserLookAhead {
66 static ParserLookAhead make(
int offset,
int bitwidth);
68 void peek(
const char *data, ByteContainer *res)
const;
71 static_assert(std::is_pod<ParserLookAhead>::value,
72 "ParserLookAhead is used in union and we assume it is POD data");
75 virtual ~ParserOp() {}
76 virtual void operator()(Packet *pkt,
const char *data,
77 size_t *bytes_parsed)
const = 0;
82 struct ParserOpSet : ParserOp {
86 ParserOpSet(header_id_t header,
int offset,
const T &src)
87 : dst({header, offset}), src(src) { }
89 void operator()(Packet *pkt,
const char *data,
90 size_t *bytes_parsed)
const override;
93 class ParseSwitchKeyBuilder {
95 void push_back_field(header_id_t header,
int field_offset,
int bitwidth);
97 void push_back_stack_field(header_stack_id_t header_stack,
int field_offset,
100 void push_back_union_stack_field(header_union_stack_id_t header_union_stack,
101 size_t header_offset,
int field_offset,
104 void push_back_lookahead(
int offset,
int bitwidth);
106 std::vector<int> get_bitwidths()
const;
108 void operator()(
const PHV &phv,
const char *data, ByteContainer *key)
const;
112 enum {FIELD, LOOKAHEAD, STACK_FIELD, UNION_STACK_FIELD} tag{};
118 header_union_stack_id_t header_union_stack;
119 size_t header_offset;
122 ParserLookAhead lookahead;
125 static Entry make_field(header_id_t header,
int offset);
127 static Entry make_stack_field(header_stack_id_t header_stack,
int offset);
129 static Entry make_union_stack_field(
130 header_union_stack_id_t header_union_stack,
size_t header_offset,
133 static Entry make_lookahead(
int offset,
int bitwidth);
136 std::vector<Entry> entries{};
137 std::vector<int> bitwidths{};
142 class ParseVSetIface {
146 INVALID_PARSE_VSET_NAME,
150 virtual ~ParseVSetIface() { }
152 virtual void add(
const ByteContainer &v) = 0;
154 virtual void remove(
const ByteContainer &v) = 0;
156 virtual bool contains(
const ByteContainer &v)
const = 0;
158 virtual void clear() = 0;
160 virtual size_t size()
const = 0;
169 class ParseVSet :
public NamedP4Object,
public ParseVSetIface {
170 template <
typename P>
friend class ParseSwitchCaseVSet;
171 using Lock = std::unique_lock<std::mutex>;
174 using ErrorCode = ParseVSetIface::ErrorCode;
176 ParseVSet(
const std::string &name, p4object_id_t
id,
177 size_t compressed_bitwidth);
181 void add(
const ByteContainer &v)
override;
183 void remove(
const ByteContainer &v)
override;
185 bool contains(
const ByteContainer &v)
const override;
187 void clear()
override;
189 size_t size()
const override;
191 size_t get_compressed_bitwidth()
const;
193 std::vector<ByteContainer> get()
const;
196 void add_shadow(ParseVSetIface *shadow);
198 size_t compressed_bitwidth;
202 mutable std::mutex shadows_mutex{};
203 std::vector<ParseVSetIface *> shadows{};
204 std::unique_ptr<ParseVSetBase> base;
207 class ParseSwitchCaseIface {
209 virtual ~ParseSwitchCaseIface() { }
211 virtual bool match(
const ByteContainer &input,
212 const ParseState **state)
const = 0;
214 static std::unique_ptr<ParseSwitchCaseIface>
215 make_case(
const ByteContainer &key,
const ParseState *next_state);
217 static std::unique_ptr<ParseSwitchCaseIface>
218 make_case_with_mask(
const ByteContainer &key,
const ByteContainer &mask,
219 const ParseState *next_state);
221 static std::unique_ptr<ParseSwitchCaseIface>
222 make_case_vset(ParseVSet *vset, std::vector<int> bitwidths,
223 const ParseState *next_state);
225 static std::unique_ptr<ParseSwitchCaseIface>
226 make_case_vset_with_mask(ParseVSet *vset,
const ByteContainer &mask,
227 std::vector<int> bitwidths,
228 const ParseState *next_state);
231 class ParseState :
public NamedP4Object {
233 ParseState(
const std::string &name, p4object_id_t
id);
235 void add_extract(header_id_t header);
236 void add_extract_VL(header_id_t header,
237 const ArithExpression &field_length_expr,
238 size_t max_header_bytes);
239 void add_extract_to_stack(header_stack_id_t header_stack);
240 void add_extract_to_stack_VL(header_stack_id_t header_stack,
241 const ArithExpression &field_length_expr,
242 size_t max_header_bytes);
243 void add_extract_to_union_stack(header_union_stack_id_t header_union_stack,
244 size_t header_offset);
245 void add_extract_to_union_stack_VL(header_union_stack_id_t header_union_stack,
246 size_t header_offset,
247 const ArithExpression &field_length_expr,
248 size_t max_header_bytes);
250 void add_set_from_field(header_id_t dst_header,
int dst_offset,
251 header_id_t src_header,
int src_offset);
253 void add_set_from_data(header_id_t dst_header,
int dst_offset,
256 void add_set_from_lookahead(header_id_t dst_header,
int dst_offset,
257 int src_offset,
int src_bitwidth);
259 void add_set_from_expression(header_id_t dst_header,
int dst_offset,
260 const ArithExpression &expr);
262 void add_verify(
const BoolExpression &condition,
263 const ArithExpression &error_expr);
265 void add_method_call(ActionFn *action_fn);
267 void add_shift(
size_t shift_bytes);
269 void add_advance_from_data(
const Data &shift_bits);
270 void add_advance_from_expression(
const ArithExpression &shift_bits);
271 void add_advance_from_field(header_id_t shift_header,
int shift_offset);
273 void set_key_builder(
const ParseSwitchKeyBuilder &builder);
275 void add_switch_case(
const ByteContainer &key,
const ParseState *next_state);
276 void add_switch_case(
int nbytes_key,
const char *key,
277 const ParseState *next_state);
279 void add_switch_case_with_mask(
const ByteContainer &key,
280 const ByteContainer &mask,
281 const ParseState *next_state);
282 void add_switch_case_with_mask(
int nbytes_key,
const char *key,
284 const ParseState *next_state);
286 void add_switch_case_vset(ParseVSet *vset,
const ParseState *next_state);
288 void add_switch_case_vset_with_mask(ParseVSet *vset,
289 const ByteContainer &mask,
290 const ParseState *next_state);
292 void set_default_switch_case(
const ParseState *default_next);
294 int expected_switch_case_key_size()
const;
297 ParseState(
const ParseState& other) =
delete;
300 ParseState &operator =(
const ParseState& other) =
delete;
303 ParseState(ParseState&& other)=
default;
306 ParseState &operator =(ParseState &&other) =
default;
308 const ParseState *operator()(Packet *pkt,
const char *data,
309 size_t *bytes_parsed)
const;
312 const ParseState *find_next_state(Packet *pkt,
const char *data,
313 size_t *bytes_parsed)
const;
315 std::vector<std::unique_ptr<ParserOp> > parser_ops{};
316 RegisterSync register_sync{};
318 ParseSwitchKeyBuilder key_builder{};
319 std::vector<std::unique_ptr<ParseSwitchCaseIface> > parser_switch{};
320 const ParseState *default_next_state{
nullptr};
326 Parser(
const std::string &name, p4object_id_t
id,
329 void set_init_state(
const ParseState *state);
331 void add_checksum(
const Checksum *checksum);
351 void verify_checksums(
Packet *pkt)
const;
353 const ParseState *init_state;
356 std::vector<const Checksum *> checksums{};
361 #endif // BM_BM_SIM_PARSER_H_