61 #ifndef BM_BM_SIM_SWITCH_H_
62 #define BM_BM_SIM_SWITCH_H_
64 #include <condition_variable>
71 #include <unordered_map>
75 #include <boost/thread/shared_mutex.hpp>
77 #include "action_profile.h"
80 #include "device_id.h"
83 #include "phv_source.h"
85 #include "runtime_interface.h"
107 explicit SwitchWContexts(
size_t nb_cxts = 1u,
bool enable_swap =
false);
113 return &contexts.at(cxt_id);
116 int receive(
port_t port_num,
const char *buffer,
int len);
136 std::string get_debugger_addr()
const;
139 std::string get_event_logger_addr()
const;
159 const std::string &field_name);
164 const std::string &field_name)
const {
165 return contexts.at(cxt_id).field_exists(header_name, field_name);
180 const std::string &field_name);
193 const std::string &act_prof_name,
194 std::shared_ptr<ActionProfile::GroupSelectionIface> selector);
199 int init_objects(
const std::string &json_path, device_id_t device_id = 0,
200 std::shared_ptr<TransportIface> notif_transport =
nullptr);
202 int init_objects_empty(device_id_t dev_id,
203 std::shared_ptr<TransportIface> transport);
230 int argc,
char *argv[],
232 std::shared_ptr<TransportIface> my_transport =
nullptr,
233 std::unique_ptr<DevMgrIface> my_dev_mgr =
nullptr);
245 const OptionsParser &parser,
246 std::shared_ptr<TransportIface> my_transport =
nullptr,
247 std::unique_ptr<DevMgrIface> my_dev_mgr =
nullptr);
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);
262 return contexts.at(cxt_id).get_component<T>();
298 return contexts.at(cxt_id).get_learn_engine();
301 AgeingMonitorIface *get_ageing_monitor(cxt_id_t cxt_id) {
302 return contexts.at(cxt_id).get_ageing_monitor();
308 return contexts.at(cxt_id).get_config_options();
315 return contexts.at(cxt_id).get_error_codes();
319 int transport_send_probe(uint64_t x)
const;
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);
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);
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 )
override {
346 return contexts.at(cxt_id).mt_add_entry(
347 table_name, match_key, action_name,
348 std::move(action_data), handle, priority);
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));
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);
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);
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));
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);
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);
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);
411 mt_act_prof_modify_member(cxt_id_t cxt_id,
412 const std::string &act_prof_name,
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));
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);
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);
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);
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);
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);
457 mt_act_prof_get_member(cxt_id_t cxt_id,
const std::string &act_prof_name,
459 ActionProfile::Member *member)
const override {
460 return contexts.at(cxt_id).mt_act_prof_get_member(
461 act_prof_name, mbr, member);
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);
471 mt_act_prof_get_group(cxt_id_t cxt_id,
const std::string &act_prof_name,
473 ActionProfile::Group *group)
const override {
474 return contexts.at(cxt_id).mt_act_prof_get_group(act_prof_name, grp, group);
480 mt_indirect_add_entry(cxt_id_t cxt_id,
481 const std::string &table_name,
482 const std::vector<MatchKeyParam> &match_key,
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);
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);
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);
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);
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);
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);
529 mt_indirect_ws_add_entry(cxt_id_t cxt_id,
530 const std::string &table_name,
531 const std::vector<MatchKeyParam> &match_key,
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);
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);
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(
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);
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);
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);
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);
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);
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);
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);
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>(
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>(
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>(
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);
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);
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);
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);
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);
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);
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);
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);
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);
700 Counter::CounterErrorCode
701 read_counters(cxt_id_t cxt_id,
702 const std::string &counter_name,
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);
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);
716 Counter::CounterErrorCode
717 write_counters(cxt_id_t cxt_id,
718 const std::string &counter_name,
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);
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);
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);
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);
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);
754 register_read(cxt_id_t cxt_id,
755 const std::string ®ister_name,
756 const size_t idx, Data *value)
override {
757 return contexts.at(cxt_id).register_read(register_name, idx, value);
761 register_read_all(cxt_id_t cxt_id,
762 const std::string ®ister_name)
override {
763 return contexts.at(cxt_id).register_read_all(register_name);
767 register_write(cxt_id_t cxt_id,
768 const std::string ®ister_name,
769 const size_t idx, Data value)
override {
770 return contexts.at(cxt_id).register_write(
771 register_name, idx, std::move(value));
775 register_write_range(cxt_id_t cxt_id,
776 const std::string ®ister_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));
784 register_reset(cxt_id_t cxt_id,
const std::string ®ister_name)
override {
785 return contexts.at(cxt_id).register_reset(register_name);
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);
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);
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);
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);
812 RuntimeInterface::ErrorCode
813 reset_state()
override;
815 RuntimeInterface::ErrorCode
816 serialize(std::ostream *out)
override;
818 RuntimeInterface::ErrorCode
819 load_new_config(
const std::string &new_config)
override;
821 RuntimeInterface::ErrorCode
822 swap_configs()
override;
824 std::string get_config()
const override;
825 std::string get_config_md5()
const override;
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;
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;
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;
844 cxt_id_t cxt_id,
const std::string &calc_name,
845 const ToeplitzMgr::key_t &key)
override;
850 using header_field_pair = Context::header_field_pair;
851 using ForceArith = Context::ForceArith;
853 const std::set<header_field_pair> &get_required_fields()
const {
854 return required_fields;
866 std::shared_ptr<void> ptr_ = std::static_pointer_cast<void>(ptr);
867 const auto &r = components.insert({std::type_index(
typeid(T)), ptr_});
879 return contexts.at(cxt_id).add_component<T>(ptr);
884 const std::shared_ptr<LookupStructureFactory> &new_factory) {
885 lookup_factory = new_factory;
888 int deserialize(std::istream *in);
889 int deserialize_from_file(
const std::string &state_dump_path);
892 int init_objects(std::istream *is, device_id_t dev_id,
893 std::shared_ptr<TransportIface> transport);
895 void reset_target_state();
901 virtual int receive_(
port_t port_num,
const char *buffer,
int len) = 0;
926 std::vector<Context> contexts{};
928 LookupStructureFactory *get_lookup_factory()
const {
929 return lookup_factory ? lookup_factory.get() : &default_lookup_factory;
933 std::string get_config_md5_()
const;
936 static LookupStructureFactory default_lookup_factory;
939 std::shared_ptr<LookupStructureFactory> lookup_factory{
nullptr};
941 bool enable_swap{
false};
943 std::unique_ptr<PHVSourceIface> phv_source{
nullptr};
945 std::unordered_map<std::type_index, std::shared_ptr<void> > components{};
947 std::set<header_field_pair> required_fields{};
948 ForceArith arith_objects{};
952 device_id_t device_id{};
956 std::string notifications_addr{};
957 std::shared_ptr<TransportIface> notifications_transport{
nullptr};
959 mutable boost::shared_mutex process_packet_mutex{};
961 std::string current_config{
"{}"};
962 bool config_loaded{
false};
963 mutable std::condition_variable config_loaded_cv{};
964 mutable std::mutex config_mutex{};
966 std::string event_logger_addr{};
976 explicit Switch(
bool enable_swap =
false);
983 const std::string &field_name)
const {
1038 p4object_id_t get_table_id(
const std::string &name) {
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);
1055 using SwitchWContexts::get_ageing_monitor;
1056 AgeingMonitorIface *get_ageing_monitor() {
1057 return get_ageing_monitor(0);
1062 ConfigOptionMap get_config_options()
const {
1063 return get_config_options(0);
1078 template<
typename T>
1080 return add_cxt_component<T>(0, std::move(ptr));
1085 template<
typename T>
1087 return get_cxt_component<T>(0);
1093 #endif // BM_BM_SIM_SWITCH_H_