bmv2
Designing your own switch target with bmv2
switch.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 
60 
61 #ifndef BM_BM_SIM_SWITCH_H_
62 #define BM_BM_SIM_SWITCH_H_
63 
64 #include <condition_variable>
65 #include <iosfwd>
66 #include <memory>
67 #include <set>
68 #include <string>
69 #include <typeindex>
70 #include <typeinfo>
71 #include <unordered_map>
72 #include <utility>
73 #include <vector>
74 
75 #include <boost/thread/shared_mutex.hpp>
76 
77 #include "action_profile.h"
78 #include "context.h"
79 #include "dev_mgr.h"
80 #include "device_id.h"
81 #include "learning.h"
82 #include "lookup_structures.h"
83 #include "phv_source.h"
84 #include "queue.h"
85 #include "runtime_interface.h"
86 #include "target_parser.h"
87 
88 namespace bm {
89 
90 class OptionsParser;
91 class Packet;
92 
93 // multiple inheritance in accordance with Google C++ guidelines:
94 // "Multiple inheritance is allowed only when all superclasses, with the
95 // possible exception of the first one, are pure interfaces. In order to ensure
96 // that they remain pure interfaces, they must end with the Interface suffix."
97 //
100 class SwitchWContexts : public DevMgr, public RuntimeInterface {
101  friend class Switch;
102 
103  public:
107  explicit SwitchWContexts(size_t nb_cxts = 1u, bool enable_swap = false);
108 
109  // TODO(antonin): return reference instead?
112  Context *get_context(cxt_id_t cxt_id = 0u) {
113  return &contexts.at(cxt_id);
114  }
115 
116  int receive(port_t port_num, const char *buffer, int len);
117 
124  void start_and_return();
125 
127  int get_runtime_port() const { return thrift_port; }
128 
130  device_id_t get_device_id() const { return device_id; }
131 
133  std::string get_notifications_addr() const { return notifications_addr; }
134 
135  // Returns empty string ("") if debugger disabled
136  std::string get_debugger_addr() const;
137 
138  // Returns empty string ("") if event logger disabled
139  std::string get_event_logger_addr() const;
140 
142  void enable_config_swap();
143 
145  void disable_config_swap();
146 
158  void add_required_field(const std::string &header_name,
159  const std::string &field_name);
160 
163  bool field_exists(cxt_id_t cxt_id, const std::string &header_name,
164  const std::string &field_name) const {
165  return contexts.at(cxt_id).field_exists(header_name, field_name);
166  }
167 
179  void force_arith_field(const std::string &header_name,
180  const std::string &field_name);
181 
186  void force_arith_header(const std::string &header_name);
187 
191  bool set_group_selector(
192  cxt_id_t cxt_id,
193  const std::string &act_prof_name,
194  std::shared_ptr<ActionProfile::GroupSelectionIface> selector);
195 
197  size_t get_nb_cxts() { return nb_cxts; }
198 
199  int init_objects(const std::string &json_path, device_id_t device_id = 0,
200  std::shared_ptr<TransportIface> notif_transport = nullptr);
201 
202  int init_objects_empty(device_id_t dev_id,
203  std::shared_ptr<TransportIface> transport);
204 
230  int argc, char *argv[],
231  TargetParserIface *tp = nullptr,
232  std::shared_ptr<TransportIface> my_transport = nullptr,
233  std::unique_ptr<DevMgrIface> my_dev_mgr = nullptr);
234 
245  const OptionsParser &parser,
246  std::shared_ptr<TransportIface> my_transport = nullptr,
247  std::unique_ptr<DevMgrIface> my_dev_mgr = nullptr);
248 
251  template<typename T>
252  std::shared_ptr<T> get_component() {
253  const auto &search = components.find(std::type_index(typeid(T)));
254  if (search == components.end()) return nullptr;
255  return std::static_pointer_cast<T>(search->second);
256  }
257 
260  template<typename T>
261  std::shared_ptr<T> get_cxt_component(cxt_id_t cxt_id) {
262  return contexts.at(cxt_id).get_component<T>();
263  }
264 
267  int swap_requested();
268 
276  int do_swap();
277 
282 
284  std::unique_ptr<Packet> new_packet_ptr(cxt_id_t cxt_id, port_t ingress_port,
285  packet_id_t id, int ingress_length,
286  // cpplint false positive
287  // NOLINTNEXTLINE(whitespace/operators)
288  PacketBuffer &&buffer);
289 
291  Packet new_packet(cxt_id_t cxt_id, port_t ingress_port, packet_id_t id,
292  // cpplint false positive
293  // NOLINTNEXTLINE(whitespace/operators)
294  int ingress_length, PacketBuffer &&buffer);
295 
297  LearnEngineIface *get_learn_engine(cxt_id_t cxt_id) {
298  return contexts.at(cxt_id).get_learn_engine();
299  }
300 
301  AgeingMonitorIface *get_ageing_monitor(cxt_id_t cxt_id) {
302  return contexts.at(cxt_id).get_ageing_monitor();
303  }
304 
307  ConfigOptionMap get_config_options(cxt_id_t cxt_id) const {
308  return contexts.at(cxt_id).get_config_options();
309  }
310 
314  ErrorCodeMap get_error_codes(cxt_id_t cxt_id) const {
315  return contexts.at(cxt_id).get_error_codes();
316  }
317 
318  // meant for testing
319  int transport_send_probe(uint64_t x) const;
320 
321  // ---------- RuntimeInterface ----------
322 
323  MatchErrorCode
324  mt_get_num_entries(cxt_id_t cxt_id,
325  const std::string &table_name,
326  size_t *num_entries) const override {
327  return contexts.at(cxt_id).mt_get_num_entries(table_name, num_entries);
328  }
329 
330  MatchErrorCode
331  mt_clear_entries(cxt_id_t cxt_id,
332  const std::string &table_name,
333  bool reset_default_entry) override {
334  return contexts.at(cxt_id).mt_clear_entries(table_name,
335  reset_default_entry);
336  }
337 
338  MatchErrorCode
339  mt_add_entry(cxt_id_t cxt_id,
340  const std::string &table_name,
341  const std::vector<MatchKeyParam> &match_key,
342  const std::string &action_name,
343  ActionData action_data,
344  entry_handle_t *handle,
345  int priority = -1 /*only used for ternary*/) override {
346  return contexts.at(cxt_id).mt_add_entry(
347  table_name, match_key, action_name,
348  std::move(action_data), handle, priority);
349  }
350 
351  MatchErrorCode
352  mt_set_default_action(cxt_id_t cxt_id,
353  const std::string &table_name,
354  const std::string &action_name,
355  ActionData action_data) override {
356  return contexts.at(cxt_id).mt_set_default_action(
357  table_name, action_name, std::move(action_data));
358  }
359 
360  MatchErrorCode
361  mt_reset_default_entry(cxt_id_t cxt_id,
362  const std::string &table_name) override {
363  return contexts.at(cxt_id).mt_reset_default_entry(table_name);
364  }
365 
366  MatchErrorCode
367  mt_delete_entry(cxt_id_t cxt_id,
368  const std::string &table_name,
369  entry_handle_t handle) override {
370  return contexts.at(cxt_id).mt_delete_entry(table_name, handle);
371  }
372 
373  MatchErrorCode
374  mt_modify_entry(cxt_id_t cxt_id,
375  const std::string &table_name,
376  entry_handle_t handle,
377  const std::string &action_name,
378  ActionData action_data) override {
379  return contexts.at(cxt_id).mt_modify_entry(
380  table_name, handle, action_name, std::move(action_data));
381  }
382 
383  MatchErrorCode
384  mt_set_entry_ttl(cxt_id_t cxt_id,
385  const std::string &table_name,
386  entry_handle_t handle,
387  unsigned int ttl_ms) override {
388  return contexts.at(cxt_id).mt_set_entry_ttl(table_name, handle, ttl_ms);
389  }
390 
391  // action profiles
392 
393  MatchErrorCode
394  mt_act_prof_add_member(cxt_id_t cxt_id,
395  const std::string &act_prof_name,
396  const std::string &action_name,
397  ActionData action_data,
398  mbr_hdl_t *mbr) override {
399  return contexts.at(cxt_id).mt_act_prof_add_member(
400  act_prof_name, action_name, std::move(action_data), mbr);
401  }
402 
403  MatchErrorCode
404  mt_act_prof_delete_member(cxt_id_t cxt_id,
405  const std::string &act_prof_name,
406  mbr_hdl_t mbr) override {
407  return contexts.at(cxt_id).mt_act_prof_delete_member(act_prof_name, mbr);
408  }
409 
410  MatchErrorCode
411  mt_act_prof_modify_member(cxt_id_t cxt_id,
412  const std::string &act_prof_name,
413  mbr_hdl_t mbr,
414  const std::string &action_name,
415  ActionData action_data) override {
416  return contexts.at(cxt_id).mt_act_prof_modify_member(
417  act_prof_name, mbr, action_name, std::move(action_data));
418  }
419 
420  MatchErrorCode
421  mt_act_prof_create_group(cxt_id_t cxt_id,
422  const std::string &act_prof_name,
423  grp_hdl_t *grp) override {
424  return contexts.at(cxt_id).mt_act_prof_create_group(act_prof_name, grp);
425  }
426 
427  MatchErrorCode
428  mt_act_prof_delete_group(cxt_id_t cxt_id,
429  const std::string &act_prof_name,
430  grp_hdl_t grp) override {
431  return contexts.at(cxt_id).mt_act_prof_delete_group(act_prof_name, grp);
432  }
433 
434  MatchErrorCode
435  mt_act_prof_add_member_to_group(cxt_id_t cxt_id,
436  const std::string &act_prof_name,
437  mbr_hdl_t mbr, grp_hdl_t grp) override {
438  return contexts.at(cxt_id).mt_act_prof_add_member_to_group(
439  act_prof_name, mbr, grp);
440  }
441 
442  MatchErrorCode
443  mt_act_prof_remove_member_from_group(cxt_id_t cxt_id,
444  const std::string &act_prof_name,
445  mbr_hdl_t mbr, grp_hdl_t grp) override {
446  return contexts.at(cxt_id).mt_act_prof_remove_member_from_group(
447  act_prof_name, mbr, grp);
448  }
449 
450  std::vector<ActionProfile::Member>
451  mt_act_prof_get_members(cxt_id_t cxt_id,
452  const std::string &act_prof_name) const override {
453  return contexts.at(cxt_id).mt_act_prof_get_members(act_prof_name);
454  }
455 
456  MatchErrorCode
457  mt_act_prof_get_member(cxt_id_t cxt_id, const std::string &act_prof_name,
458  mbr_hdl_t mbr,
459  ActionProfile::Member *member) const override {
460  return contexts.at(cxt_id).mt_act_prof_get_member(
461  act_prof_name, mbr, member);
462  }
463 
464  std::vector<ActionProfile::Group>
465  mt_act_prof_get_groups(cxt_id_t cxt_id,
466  const std::string &act_prof_name) const override {
467  return contexts.at(cxt_id).mt_act_prof_get_groups(act_prof_name);
468  }
469 
470  MatchErrorCode
471  mt_act_prof_get_group(cxt_id_t cxt_id, const std::string &act_prof_name,
472  grp_hdl_t grp,
473  ActionProfile::Group *group) const override {
474  return contexts.at(cxt_id).mt_act_prof_get_group(act_prof_name, grp, group);
475  }
476 
477  // indirect tables
478 
479  MatchErrorCode
480  mt_indirect_add_entry(cxt_id_t cxt_id,
481  const std::string &table_name,
482  const std::vector<MatchKeyParam> &match_key,
483  mbr_hdl_t mbr,
484  entry_handle_t *handle,
485  int priority = 1) override {
486  return contexts.at(cxt_id).mt_indirect_add_entry(
487  table_name, match_key, mbr, handle, priority);
488  }
489 
490  MatchErrorCode
491  mt_indirect_modify_entry(cxt_id_t cxt_id,
492  const std::string &table_name,
493  entry_handle_t handle,
494  mbr_hdl_t mbr) override {
495  return contexts.at(cxt_id).mt_indirect_modify_entry(
496  table_name, handle, mbr);
497  }
498 
499  MatchErrorCode
500  mt_indirect_delete_entry(cxt_id_t cxt_id,
501  const std::string &table_name,
502  entry_handle_t handle) override {
503  return contexts.at(cxt_id).mt_indirect_delete_entry(table_name, handle);
504  }
505 
506  MatchErrorCode
507  mt_indirect_set_entry_ttl(cxt_id_t cxt_id,
508  const std::string &table_name,
509  entry_handle_t handle,
510  unsigned int ttl_ms) override {
511  return contexts.at(cxt_id).mt_indirect_set_entry_ttl(
512  table_name, handle, ttl_ms);
513  }
514 
515  MatchErrorCode
516  mt_indirect_set_default_member(cxt_id_t cxt_id,
517  const std::string &table_name,
518  mbr_hdl_t mbr) override {
519  return contexts.at(cxt_id).mt_indirect_set_default_member(table_name, mbr);
520  }
521 
522  MatchErrorCode
523  mt_indirect_reset_default_entry(cxt_id_t cxt_id,
524  const std::string &table_name) override {
525  return contexts.at(cxt_id).mt_indirect_reset_default_entry(table_name);
526  }
527 
528  MatchErrorCode
529  mt_indirect_ws_add_entry(cxt_id_t cxt_id,
530  const std::string &table_name,
531  const std::vector<MatchKeyParam> &match_key,
532  grp_hdl_t grp,
533  entry_handle_t *handle,
534  int priority = 1) override {
535  return contexts.at(cxt_id).mt_indirect_ws_add_entry(
536  table_name, match_key, grp, handle, priority);
537  }
538 
539  MatchErrorCode
540  mt_indirect_ws_modify_entry(cxt_id_t cxt_id,
541  const std::string &table_name,
542  entry_handle_t handle,
543  grp_hdl_t grp) override {
544  return contexts.at(cxt_id).mt_indirect_ws_modify_entry(
545  table_name, handle, grp);
546  }
547 
548  MatchErrorCode
549  mt_indirect_ws_set_default_group(cxt_id_t cxt_id,
550  const std::string &table_name,
551  grp_hdl_t grp) override {
552  return contexts.at(cxt_id).mt_indirect_ws_set_default_group(
553  table_name, grp);
554  }
555 
556  MatchTableType
557  mt_get_type(cxt_id_t cxt_id, const std::string &table_name) const override {
558  return contexts.at(cxt_id).mt_get_type(table_name);
559  }
560 
561  std::vector<MatchTable::Entry>
562  mt_get_entries(cxt_id_t cxt_id,
563  const std::string &table_name) const override {
564  return contexts.at(cxt_id).mt_get_entries<MatchTable>(table_name);
565  }
566 
567  std::vector<MatchTableIndirect::Entry>
568  mt_indirect_get_entries(cxt_id_t cxt_id,
569  const std::string &table_name) const override {
570  return contexts.at(cxt_id).mt_get_entries<MatchTableIndirect>(table_name);
571  }
572 
573  std::vector<MatchTableIndirectWS::Entry>
574  mt_indirect_ws_get_entries(cxt_id_t cxt_id,
575  const std::string &table_name) const override {
576  return contexts.at(cxt_id).mt_get_entries<MatchTableIndirectWS>(table_name);
577  }
578 
579  MatchErrorCode
580  mt_get_entry(cxt_id_t cxt_id, const std::string &table_name,
581  entry_handle_t handle, MatchTable::Entry *entry) const override {
582  return contexts.at(cxt_id).mt_get_entry<MatchTable>(
583  table_name, handle, entry);
584  }
585 
586  MatchErrorCode
587  mt_indirect_get_entry(cxt_id_t cxt_id, const std::string &table_name,
588  entry_handle_t handle,
589  MatchTableIndirect::Entry *entry) const override {
590  return contexts.at(cxt_id).mt_get_entry<MatchTableIndirect>(
591  table_name, handle, entry);
592  }
593 
594  MatchErrorCode
595  mt_indirect_ws_get_entry(cxt_id_t cxt_id, const std::string &table_name,
596  entry_handle_t handle,
597  MatchTableIndirectWS::Entry *entry) const override {
598  return contexts.at(cxt_id).mt_get_entry<MatchTableIndirectWS>(
599  table_name, handle, entry);
600  }
601 
602  MatchErrorCode
603  mt_get_default_entry(cxt_id_t cxt_id, const std::string &table_name,
604  MatchTable::Entry *entry) const override {
605  return contexts.at(cxt_id).mt_get_default_entry<MatchTable>(
606  table_name, entry);
607  }
608 
609  MatchErrorCode
610  mt_indirect_get_default_entry(
611  cxt_id_t cxt_id, const std::string &table_name,
612  MatchTableIndirect::Entry *entry) const override {
613  return contexts.at(cxt_id).mt_get_default_entry<MatchTableIndirect>(
614  table_name, entry);
615  }
616 
617  MatchErrorCode
618  mt_indirect_ws_get_default_entry(
619  cxt_id_t cxt_id, const std::string &table_name,
620  MatchTableIndirectWS::Entry *entry) const override {
621  return contexts.at(cxt_id).mt_get_default_entry<MatchTableIndirectWS>(
622  table_name, entry);
623  }
624 
625  MatchErrorCode
626  mt_get_entry_from_key(cxt_id_t cxt_id, const std::string &table_name,
627  const std::vector<MatchKeyParam> &match_key,
628  MatchTable::Entry *entry,
629  int priority = 1) const override {
630  return contexts.at(cxt_id).mt_get_entry_from_key<MatchTable>(
631  table_name, match_key, entry, priority);
632  }
633 
634  MatchErrorCode
635  mt_indirect_get_entry_from_key(cxt_id_t cxt_id, const std::string &table_name,
636  const std::vector<MatchKeyParam> &match_key,
637  MatchTableIndirect::Entry *entry,
638  int priority = 1) const override {
639  return contexts.at(cxt_id).mt_get_entry_from_key<MatchTableIndirect>(
640  table_name, match_key, entry, priority);
641  }
642 
643  MatchErrorCode
644  mt_indirect_ws_get_entry_from_key(cxt_id_t cxt_id,
645  const std::string &table_name,
646  const std::vector<MatchKeyParam> &match_key,
647  MatchTableIndirectWS::Entry *entry,
648  int priority = 1) const override {
649  return contexts.at(cxt_id).mt_get_entry_from_key<MatchTableIndirectWS>(
650  table_name, match_key, entry, priority);
651  }
652 
653  MatchErrorCode
654  mt_read_counters(cxt_id_t cxt_id,
655  const std::string &table_name,
656  entry_handle_t handle,
657  MatchTableAbstract::counter_value_t *bytes,
658  MatchTableAbstract::counter_value_t *packets) override {
659  return contexts.at(cxt_id).mt_read_counters(
660  table_name, handle, bytes, packets);
661  }
662 
663  MatchErrorCode
664  mt_reset_counters(cxt_id_t cxt_id,
665  const std::string &table_name) override {
666  return contexts.at(cxt_id).mt_reset_counters(table_name);
667  }
668 
669  MatchErrorCode
670  mt_write_counters(cxt_id_t cxt_id,
671  const std::string &table_name,
672  entry_handle_t handle,
673  MatchTableAbstract::counter_value_t bytes,
674  MatchTableAbstract::counter_value_t packets) override {
675  return contexts.at(cxt_id).mt_write_counters(
676  table_name, handle, bytes, packets);
677  }
678 
679  MatchErrorCode
680  mt_set_meter_rates(
681  cxt_id_t cxt_id, const std::string &table_name, entry_handle_t handle,
682  const std::vector<Meter::rate_config_t> &configs) override {
683  return contexts.at(cxt_id).mt_set_meter_rates(table_name, handle, configs);
684  }
685 
686  MatchErrorCode
687  mt_get_meter_rates(
688  cxt_id_t cxt_id, const std::string &table_name, entry_handle_t handle,
689  std::vector<Meter::rate_config_t> *configs) override {
690  return contexts.at(cxt_id).mt_get_meter_rates(table_name, handle, configs);
691  }
692 
693  MatchErrorCode
694  mt_reset_meter_rates(
695  cxt_id_t cxt_id, const std::string &table_name,
696  entry_handle_t handle) override {
697  return contexts.at(cxt_id).mt_reset_meter_rates(table_name, handle);
698  }
699 
700  Counter::CounterErrorCode
701  read_counters(cxt_id_t cxt_id,
702  const std::string &counter_name,
703  size_t index,
704  MatchTableAbstract::counter_value_t *bytes,
705  MatchTableAbstract::counter_value_t *packets) override {
706  return contexts.at(cxt_id).read_counters(
707  counter_name, index, bytes, packets);
708  }
709 
710  Counter::CounterErrorCode
711  reset_counters(cxt_id_t cxt_id,
712  const std::string &counter_name) override {
713  return contexts.at(cxt_id).reset_counters(counter_name);
714  }
715 
716  Counter::CounterErrorCode
717  write_counters(cxt_id_t cxt_id,
718  const std::string &counter_name,
719  size_t index,
720  MatchTableAbstract::counter_value_t bytes,
721  MatchTableAbstract::counter_value_t packets) override {
722  return contexts.at(cxt_id).write_counters(
723  counter_name, index, bytes, packets);
724  }
725 
726  MeterErrorCode
727  meter_array_set_rates(
728  cxt_id_t cxt_id, const std::string &meter_name,
729  const std::vector<Meter::rate_config_t> &configs) override {
730  return contexts.at(cxt_id).meter_array_set_rates(meter_name, configs);
731  }
732 
733  MeterErrorCode
734  meter_set_rates(cxt_id_t cxt_id,
735  const std::string &meter_name, size_t idx,
736  const std::vector<Meter::rate_config_t> &configs) override {
737  return contexts.at(cxt_id).meter_set_rates(meter_name, idx, configs);
738  }
739 
740  MeterErrorCode
741  meter_get_rates(cxt_id_t cxt_id,
742  const std::string &meter_name, size_t idx,
743  std::vector<Meter::rate_config_t> *configs) override {
744  return contexts.at(cxt_id).meter_get_rates(meter_name, idx, configs);
745  }
746 
747  MeterErrorCode
748  meter_reset_rates(cxt_id_t cxt_id,
749  const std::string &meter_name, size_t idx) override {
750  return contexts.at(cxt_id).meter_reset_rates(meter_name, idx);
751  }
752 
753  RegisterErrorCode
754  register_read(cxt_id_t cxt_id,
755  const std::string &register_name,
756  const size_t idx, Data *value) override {
757  return contexts.at(cxt_id).register_read(register_name, idx, value);
758  }
759 
760  std::vector<Data>
761  register_read_all(cxt_id_t cxt_id,
762  const std::string &register_name) override {
763  return contexts.at(cxt_id).register_read_all(register_name);
764  }
765 
766  RegisterErrorCode
767  register_write(cxt_id_t cxt_id,
768  const std::string &register_name,
769  const size_t idx, Data value) override {
770  return contexts.at(cxt_id).register_write(
771  register_name, idx, std::move(value));
772  }
773 
774  RegisterErrorCode
775  register_write_range(cxt_id_t cxt_id,
776  const std::string &register_name,
777  const size_t start, const size_t end,
778  Data value) override {
779  return contexts.at(cxt_id).register_write_range(
780  register_name, start, end, std::move(value));
781  }
782 
783  RegisterErrorCode
784  register_reset(cxt_id_t cxt_id, const std::string &register_name) override {
785  return contexts.at(cxt_id).register_reset(register_name);
786  }
787 
788  ParseVSet::ErrorCode
789  parse_vset_add(cxt_id_t cxt_id, const std::string &parse_vset_name,
790  const ByteContainer &value) override {
791  return contexts.at(cxt_id).parse_vset_add(parse_vset_name, value);
792  }
793 
794  ParseVSet::ErrorCode
795  parse_vset_remove(cxt_id_t cxt_id, const std::string &parse_vset_name,
796  const ByteContainer &value) override {
797  return contexts.at(cxt_id).parse_vset_remove(parse_vset_name, value);
798  }
799 
800  ParseVSet::ErrorCode
801  parse_vset_get(cxt_id_t cxt_id, const std::string &parse_vset_name,
802  std::vector<ByteContainer> *values) override {
803  return contexts.at(cxt_id).parse_vset_get(parse_vset_name, values);
804  }
805 
806  ParseVSet::ErrorCode
807  parse_vset_clear(cxt_id_t cxt_id,
808  const std::string &parse_vset_name) override {
809  return contexts.at(cxt_id).parse_vset_clear(parse_vset_name);
810  }
811 
812  RuntimeInterface::ErrorCode
813  reset_state() override;
814 
815  RuntimeInterface::ErrorCode
816  serialize(std::ostream *out) override;
817 
818  RuntimeInterface::ErrorCode
819  load_new_config(const std::string &new_config) override;
820 
821  RuntimeInterface::ErrorCode
822  swap_configs() override;
823 
824  std::string get_config() const override;
825  std::string get_config_md5() const override;
826 
827  P4Objects::IdLookupErrorCode p4objects_id_from_name(
828  cxt_id_t cxt_id, P4Objects::ResourceType type, const std::string &name,
829  p4object_id_t *id) const;
830 
831  // conscious choice not to use templates here (or could not use virtual)
832  CustomCrcErrorCode
833  set_crc16_custom_parameters(
834  cxt_id_t cxt_id, const std::string &calc_name,
835  const CustomCrcMgr<uint16_t>::crc_config_t &crc16_config) override;
836 
837  CustomCrcErrorCode
838  set_crc32_custom_parameters(
839  cxt_id_t cxt_id, const std::string &calc_name,
840  const CustomCrcMgr<uint32_t>::crc_config_t &crc32_config) override;
841 
842  ToeplitzErrorCode
843  set_toeplitz_key(
844  cxt_id_t cxt_id, const std::string &calc_name,
845  const ToeplitzMgr::key_t &key) override;
846 
847  // ---------- End RuntimeInterface ----------
848 
849  protected:
850  using header_field_pair = Context::header_field_pair;
851  using ForceArith = Context::ForceArith;
852 
853  const std::set<header_field_pair> &get_required_fields() const {
854  return required_fields;
855  }
856 
864  template<typename T>
865  bool add_component(std::shared_ptr<T> ptr) {
866  std::shared_ptr<void> ptr_ = std::static_pointer_cast<void>(ptr);
867  const auto &r = components.insert({std::type_index(typeid(T)), ptr_});
868  return r.second;
869  }
870 
877  template<typename T>
878  bool add_cxt_component(cxt_id_t cxt_id, std::shared_ptr<T> ptr) {
879  return contexts.at(cxt_id).add_component<T>(ptr);
880  }
881 
882  void
883  set_lookup_factory(
884  const std::shared_ptr<LookupStructureFactory> &new_factory) {
885  lookup_factory = new_factory;
886  }
887 
888  int deserialize(std::istream *in);
889  int deserialize_from_file(const std::string &state_dump_path);
890 
891  private:
892  int init_objects(std::istream *is, device_id_t dev_id,
893  std::shared_ptr<TransportIface> transport);
894 
895  void reset_target_state();
896 
897  void swap_notify();
898 
901  virtual int receive_(port_t port_num, const char *buffer, int len) = 0;
902 
907  virtual void start_and_return_() = 0;
908 
912  virtual void reset_target_state_() { }
913 
919  virtual void swap_notify_() { }
920 
921  private:
922  size_t nb_cxts{};
923  // TODO(antonin)
924  // Context is not-movable, but is default-constructible, so I can put it in a
925  // std::vector
926  std::vector<Context> contexts{};
927 
928  LookupStructureFactory *get_lookup_factory() const {
929  return lookup_factory ? lookup_factory.get() : &default_lookup_factory;
930  }
931 
932  // internal version of get_config_md5(), which does not acquire config_lock
933  std::string get_config_md5_() const;
934 
935  // Create an instance of the default lookup factory
936  static LookupStructureFactory default_lookup_factory;
937  // All Switches will refer to that instance unless explicitly
938  // given a factory
939  std::shared_ptr<LookupStructureFactory> lookup_factory{nullptr};
940 
941  bool enable_swap{false};
942 
943  std::unique_ptr<PHVSourceIface> phv_source{nullptr};
944 
945  std::unordered_map<std::type_index, std::shared_ptr<void> > components{};
946 
947  std::set<header_field_pair> required_fields{};
948  ForceArith arith_objects{};
949 
950  int thrift_port{};
951 
952  device_id_t device_id{};
953 
954  // same transport used for all notifications, irrespective of the thread, made
955  // possible by multi-threading support in nanomsg
956  std::string notifications_addr{};
957  std::shared_ptr<TransportIface> notifications_transport{nullptr};
958 
959  mutable boost::shared_mutex process_packet_mutex{};
960 
961  std::string current_config{"{}"}; // empty JSON config
962  bool config_loaded{false};
963  mutable std::condition_variable config_loaded_cv{};
964  mutable std::mutex config_mutex{};
965 
966  std::string event_logger_addr{};
967 };
968 
969 
973 class Switch : public SwitchWContexts {
974  public:
976  explicit Switch(bool enable_swap = false);
977 
978  // to avoid C++ name hiding
982  bool field_exists(const std::string &header_name,
983  const std::string &field_name) const {
984  return field_exists(0, header_name, field_name);
985  }
986 
987  // to avoid C++ name hiding
991  std::unique_ptr<Packet> new_packet_ptr(port_t ingress_port,
992  packet_id_t id, int ingress_length,
993  // cpplint false positive
994  // NOLINTNEXTLINE(whitespace/operators)
995  PacketBuffer &&buffer);
996 
997  // to avoid C++ name hiding
1001  Packet new_packet(port_t ingress_port, packet_id_t id, int ingress_length,
1002  // cpplint false positive
1003  // NOLINTNEXTLINE(whitespace/operators)
1004  PacketBuffer &&buffer);
1005 
1010  Pipeline *get_pipeline(const std::string &name) {
1011  return get_context(0)->get_pipeline(name);
1012  }
1013 
1018  Parser *get_parser(const std::string &name) {
1019  return get_context(0)->get_parser(name);
1020  }
1021 
1026  Deparser *get_deparser(const std::string &name) {
1027  return get_context(0)->get_deparser(name);
1028  }
1029 
1033  FieldList *get_field_list(const p4object_id_t field_list_id) {
1034  return get_context(0)->get_field_list(field_list_id);
1035  }
1036 
1037  // Added for testing, other "object types" can be added if needed
1038  p4object_id_t get_table_id(const std::string &name) {
1039  return get_context(0)->get_table_id(name);
1040  }
1041 
1042  p4object_id_t get_action_id(const std::string &table_name,
1043  const std::string &action_name) {
1044  return get_context(0)->get_action_id(table_name, action_name);
1045  }
1046 
1047  // to avoid C++ name hiding
1051  return get_learn_engine(0);
1052  }
1053 
1054  // to avoid C++ name hiding
1055  using SwitchWContexts::get_ageing_monitor;
1056  AgeingMonitorIface *get_ageing_monitor() {
1057  return get_ageing_monitor(0);
1058  }
1059 
1060  // to avoid C++ name hiding
1062  ConfigOptionMap get_config_options() const {
1063  return get_config_options(0);
1064  }
1065 
1066  // to avoid C++ name hiding
1071  return get_error_codes(0);
1072  }
1073 
1078  template<typename T>
1079  bool add_component(std::shared_ptr<T> ptr) {
1080  return add_cxt_component<T>(0, std::move(ptr));
1081  }
1082 
1085  template<typename T>
1086  std::shared_ptr<T> get_component() {
1087  return get_cxt_component<T>(0);
1088  }
1089 };
1090 
1091 } // namespace bm
1092 
1093 #endif // BM_BM_SIM_SWITCH_H_
bm::Switch
Definition: switch.h:973
lookup_structures.h
bm::Switch::get_pipeline
Pipeline * get_pipeline(const std::string &name)
Definition: switch.h:1010
bm::SwitchWContexts::init_from_options_parser
int init_from_options_parser(const OptionsParser &parser, std::shared_ptr< TransportIface > my_transport=nullptr, std::unique_ptr< DevMgrIface > my_dev_mgr=nullptr)
bm::FieldList
Definition: field_lists.h:43
bm::Switch::get_learn_engine
LearnEngineIface * get_learn_engine()
Obtain a pointer to the LearnEngine for this Switch instance.
Definition: switch.h:1050
dev_mgr.h
bm::Switch::get_field_list
FieldList * get_field_list(const p4object_id_t field_list_id)
Definition: switch.h:1033
bm::TargetParserIface
Interface for target-specific command-line options parsers.
Definition: target_parser.h:41
bm::Context::get_pipeline
Pipeline * get_pipeline(const std::string &name)
Definition: context.h:131
bm::Switch::field_exists
bool field_exists(const std::string &header_name, const std::string &field_name) const
Definition: switch.h:982
bm::SwitchWContexts::set_group_selector
bool set_group_selector(cxt_id_t cxt_id, const std::string &act_prof_name, std::shared_ptr< ActionProfile::GroupSelectionIface > selector)
bm::SwitchWContexts
Definition: switch.h:100
bm::SwitchWContexts::do_swap
int do_swap()
bm::SwitchWContexts::get_cxt_component
std::shared_ptr< T > get_cxt_component(cxt_id_t cxt_id)
Definition: switch.h:261
bm::Switch::get_deparser
Deparser * get_deparser(const std::string &name)
Definition: switch.h:1026
bm::SwitchWContexts::block_until_no_more_packets
void block_until_no_more_packets()
bm::port_t
uint32_t port_t
Integral type used to identify a given port.
Definition: packet.h:53
learning.h
bm::SwitchWContexts::disable_config_swap
void disable_config_swap()
Disable JSON config swapping for the switch.
bm::SwitchWContexts::get_error_codes
ErrorCodeMap get_error_codes(cxt_id_t cxt_id) const
Definition: switch.h:314
bm::SwitchWContexts::get_runtime_port
int get_runtime_port() const
Returns the Thrift port used for the runtime RPC server.
Definition: switch.h:127
bm::Switch::get_error_codes
ErrorCodeMap get_error_codes() const
Definition: switch.h:1070
bm::Context::get_field_list
FieldList * get_field_list(const p4object_id_t field_list_id)
Definition: context.h:149
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::SwitchWContexts::get_learn_engine
LearnEngineIface * get_learn_engine(cxt_id_t cxt_id)
Obtain a pointer to the LearnEngine for a given Context.
Definition: switch.h:297
bm::Context::get_parser
Parser * get_parser(const std::string &name)
Definition: context.h:137
target_parser.h
bm::SwitchWContexts::SwitchWContexts
SwitchWContexts(size_t nb_cxts=1u, bool enable_swap=false)
bm::SwitchWContexts::force_arith_header
void force_arith_header(const std::string &header_name)
bm::SwitchWContexts::reset_target_state_
virtual void reset_target_state_()
Definition: switch.h:912
bm::Context::get_deparser
Deparser * get_deparser(const std::string &name)
Definition: context.h:143
bm::SwitchWContexts::get_notifications_addr
std::string get_notifications_addr() const
Returns the nanomsg IPC address for this switch.
Definition: switch.h:133
bm::Context
Definition: context.h:90
bm::SwitchWContexts::get_component
std::shared_ptr< T > get_component()
Definition: switch.h:252
bm::SwitchWContexts::start_and_return
void start_and_return()
bm::SwitchWContexts::swap_requested
int swap_requested()
bm::DevMgr::port_t
PortMonitorIface::port_t port_t
Representation of a port number.
Definition: dev_mgr.h:153
queue.h
bm::Pipeline
Definition: pipeline.h:36
bm::DevMgr
Definition: dev_mgr.h:150
bm::SwitchWContexts::start_and_return_
virtual void start_and_return_()=0
bm::Switch::new_packet_ptr
std::unique_ptr< Packet > new_packet_ptr(port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
bm::SwitchWContexts::get_context
Context * get_context(cxt_id_t cxt_id=0u)
Definition: switch.h:112
bm::LearnEngineIface
Definition: learning.h:44
bm::SwitchWContexts::swap_notify_
virtual void swap_notify_()
Definition: switch.h:919
bm::SwitchWContexts::enable_config_swap
void enable_config_swap()
Enable JSON config swapping for the switch.
bm::Switch::get_parser
Parser * get_parser(const std::string &name)
Definition: switch.h:1018
bm::PacketBuffer
Definition: packet_buffer.h:48
bm::SwitchWContexts::receive_
virtual int receive_(port_t port_num, const char *buffer, int len)=0
bm::Switch::get_component
std::shared_ptr< T > get_component()
Definition: switch.h:1086
bm::SwitchWContexts::new_packet_ptr
std::unique_ptr< Packet > new_packet_ptr(cxt_id_t cxt_id, port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
Construct and return a Packet instance for the given cxt_id.
bm::SwitchWContexts::field_exists
bool field_exists(cxt_id_t cxt_id, const std::string &header_name, const std::string &field_name) const
Definition: switch.h:163
bm::Parser
Implements a P4 parser.
Definition: parser.h:324
context.h
bm::SwitchWContexts::force_arith_field
void force_arith_field(const std::string &header_name, const std::string &field_name)
bm::SwitchWContexts::add_required_field
void add_required_field(const std::string &header_name, const std::string &field_name)
bm::SwitchWContexts::new_packet
Packet new_packet(cxt_id_t cxt_id, port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
Construct and return a Packet instance for the given cxt_id.
bm::SwitchWContexts::get_config_options
ConfigOptionMap get_config_options(cxt_id_t cxt_id) const
Definition: switch.h:307
bm::ErrorCodeMap
A bi-directional map between error codes and their P4 names.
Definition: parser_error.h:66
bm::Switch::add_component
bool add_component(std::shared_ptr< T > ptr)
Definition: switch.h:1079
bm::Deparser
Definition: deparser.h:50
bm::Switch::new_packet
Packet new_packet(port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
bm::SwitchWContexts::get_device_id
device_id_t get_device_id() const
Returns the device id for this switch instance.
Definition: switch.h:130
bm::SwitchWContexts::add_cxt_component
bool add_cxt_component(cxt_id_t cxt_id, std::shared_ptr< T > ptr)
Definition: switch.h:878
bm::SwitchWContexts::get_nb_cxts
size_t get_nb_cxts()
Get the number of contexts included in this switch.
Definition: switch.h:197
bm::SwitchWContexts::add_component
bool add_component(std::shared_ptr< T > ptr)
Definition: switch.h:865
bm::SwitchWContexts::init_from_command_line_options
int init_from_command_line_options(int argc, char *argv[], TargetParserIface *tp=nullptr, std::shared_ptr< TransportIface > my_transport=nullptr, std::unique_ptr< DevMgrIface > my_dev_mgr=nullptr)