bmv2
Designing your own switch target with bmv2
Loading...
Searching...
No Matches
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
88namespace bm {
89
90class OptionsParser;
91class 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//
100class 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
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
143
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
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
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
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
973class 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
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_
Definition context.h:90
FieldList * get_field_list(const p4object_id_t field_list_id)
Definition context.h:149
Deparser * get_deparser(const std::string &name)
Definition context.h:143
Pipeline * get_pipeline(const std::string &name)
Definition context.h:131
Parser * get_parser(const std::string &name)
Definition context.h:137
Definition deparser.h:50
Definition dev_mgr.h:150
PortMonitorIface::port_t port_t
Representation of a port number.
Definition dev_mgr.h:153
A bi-directional map between error codes and their P4 names.
Definition parser_error.h:66
Definition field_lists.h:43
Definition learning.h:44
Definition packet_buffer.h:48
Definition packet.h:98
Implements a P4 parser.
Definition parser.h:324
Definition pipeline.h:36
Definition switch.h:100
int get_runtime_port() const
Returns the Thrift port used for the runtime RPC server.
Definition switch.h:127
size_t get_nb_cxts()
Get the number of contexts included in this switch.
Definition switch.h:197
ConfigOptionMap get_config_options(cxt_id_t cxt_id) const
Definition switch.h:307
Context * get_context(cxt_id_t cxt_id=0u)
Definition switch.h:112
int init_from_options_parser(const OptionsParser &parser, std::shared_ptr< TransportIface > my_transport=nullptr, std::unique_ptr< DevMgrIface > my_dev_mgr=nullptr)
void block_until_no_more_packets()
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.
std::shared_ptr< T > get_component()
Definition switch.h:252
virtual int receive_(port_t port_num, const char *buffer, int len)=0
SwitchWContexts(size_t nb_cxts=1u, bool enable_swap=false)
bool field_exists(cxt_id_t cxt_id, const std::string &header_name, const std::string &field_name) const
Definition switch.h:163
void force_arith_field(const std::string &header_name, const std::string &field_name)
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.
LearnEngineIface * get_learn_engine(cxt_id_t cxt_id)
Obtain a pointer to the LearnEngine for a given Context.
Definition switch.h:297
virtual void reset_target_state_()
Definition switch.h:912
void enable_config_swap()
Enable JSON config swapping for the switch.
std::string get_notifications_addr() const
Returns the nanomsg IPC address for this switch.
Definition switch.h:133
bool add_component(std::shared_ptr< T > ptr)
Definition switch.h:865
std::shared_ptr< T > get_cxt_component(cxt_id_t cxt_id)
Definition switch.h:261
void add_required_field(const std::string &header_name, const std::string &field_name)
virtual void start_and_return_()=0
bool set_group_selector(cxt_id_t cxt_id, const std::string &act_prof_name, std::shared_ptr< ActionProfile::GroupSelectionIface > selector)
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)
ErrorCodeMap get_error_codes(cxt_id_t cxt_id) const
Definition switch.h:314
void force_arith_header(const std::string &header_name)
virtual void swap_notify_()
Definition switch.h:919
device_id_t get_device_id() const
Returns the device id for this switch instance.
Definition switch.h:130
bool add_cxt_component(cxt_id_t cxt_id, std::shared_ptr< T > ptr)
Definition switch.h:878
void disable_config_swap()
Disable JSON config swapping for the switch.
Definition switch.h:973
bool add_component(std::shared_ptr< T > ptr)
Definition switch.h:1079
Parser * get_parser(const std::string &name)
Definition switch.h:1018
ErrorCodeMap get_error_codes() const
Definition switch.h:1070
Packet new_packet(port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
FieldList * get_field_list(const p4object_id_t field_list_id)
Definition switch.h:1033
Switch(bool enable_swap=false)
See SwitchWContexts::SwitchWContexts()
LearnEngineIface * get_learn_engine()
Obtain a pointer to the LearnEngine for this Switch instance.
Definition switch.h:1050
std::unique_ptr< Packet > new_packet_ptr(port_t ingress_port, packet_id_t id, int ingress_length, PacketBuffer &&buffer)
Deparser * get_deparser(const std::string &name)
Definition switch.h:1026
std::shared_ptr< T > get_component()
Definition switch.h:1086
Pipeline * get_pipeline(const std::string &name)
Definition switch.h:1010
bool field_exists(const std::string &header_name, const std::string &field_name) const
Definition switch.h:982
Interface for target-specific command-line options parsers.
Definition target_parser.h:41
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