bmv2
Designing your own switch target with bmv2
|
Public Member Functions | |
SwitchWContexts (size_t nb_cxts=1u, bool enable_swap=false) | |
Context * | get_context (cxt_id_t cxt_id=0u) |
void | start_and_return () |
int | get_runtime_port () const |
Returns the Thrift port used for the runtime RPC server. More... | |
device_id_t | get_device_id () const |
Returns the device id for this switch instance. More... | |
std::string | get_notifications_addr () const |
Returns the nanomsg IPC address for this switch. More... | |
void | enable_config_swap () |
Enable JSON config swapping for the switch. More... | |
void | disable_config_swap () |
Disable JSON config swapping for the switch. More... | |
void | add_required_field (const std::string &header_name, const std::string &field_name) |
bool | field_exists (cxt_id_t cxt_id, const std::string &header_name, const std::string &field_name) const |
void | force_arith_field (const std::string &header_name, const std::string &field_name) |
void | force_arith_header (const std::string &header_name) |
bool | set_group_selector (cxt_id_t cxt_id, const std::string &act_prof_name, std::shared_ptr< ActionProfile::GroupSelectionIface > selector) |
size_t | get_nb_cxts () |
Get the number of contexts included in this switch. More... | |
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) |
int | init_from_options_parser (const OptionsParser &parser, std::shared_ptr< TransportIface > my_transport=nullptr, std::unique_ptr< DevMgrIface > my_dev_mgr=nullptr) |
template<typename T > | |
std::shared_ptr< T > | get_component () |
template<typename T > | |
std::shared_ptr< T > | get_cxt_component (cxt_id_t cxt_id) |
int | swap_requested () |
int | do_swap () |
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 . More... | |
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 . More... | |
LearnEngineIface * | get_learn_engine (cxt_id_t cxt_id) |
Obtain a pointer to the LearnEngine for a given Context. More... | |
ConfigOptionMap | get_config_options (cxt_id_t cxt_id) const |
ErrorCodeMap | get_error_codes (cxt_id_t cxt_id) const |
![]() | |
void | transmit_fn (port_t port_num, const char *buffer, int len) |
Transmits a data packet out of port port_num . More... | |
ReturnCode | register_status_cb (const PortStatus &type, const PortStatusCb &port_cb) |
Protected Member Functions | |
template<typename T > | |
bool | add_component (std::shared_ptr< T > ptr) |
template<typename T > | |
bool | add_cxt_component (cxt_id_t cxt_id, std::shared_ptr< T > ptr) |
Private Member Functions | |
virtual int | receive_ (port_t port_num, const char *buffer, int len)=0 |
virtual void | start_and_return_ ()=0 |
virtual void | reset_target_state_ () |
virtual void | swap_notify_ () |
Additional Inherited Members | |
![]() | |
using | port_t = PortMonitorIface::port_t |
Representation of a port number. More... | |
using | PortStatus = PortMonitorIface::PortStatus |
Represents the status of a port. More... | |
using | PortStatusCb = PortMonitorIface::PortStatusCb |
Signature of the cb function to call when a port status changes. More... | |
Base class for a switch implemenattion where multi-context support is required.
|
explicit |
To enable live swapping of P4-JSON configurations, enable_swap needs to be set to true
. See switch.h documentation for more information on configuration swap.
|
inlineprotected |
Add a component to this switch. Each switch maintains a map T
-> shared_ptr<T>
, which maps a type (using typeid
) to a shared pointer to an object of the same type. The pointer can be retrieved at a later time by using get_component(). This method should be used for components which are global to the switch and not specific to a Context of the switch, otherwise you can use add_cxt_component(). The pointer can be retrieved at a later time by using get_component().
|
inlineprotected |
Add a component to a context of the switch. Essentially calls Context::add_component() for the correct context. This method should be used for components which are specific to a Context (e.g. you can have one packet replication engine instance per context) and not global to the switch, otherwise you can use add_component(). The pointer can be retrieved at a later time by using get_cxt_component().
void bm::SwitchWContexts::add_required_field | ( | const std::string & | header_name, |
const std::string & | field_name | ||
) |
Specify that the field is required for this target switch, i.e. the field needs to be defined in the input JSON. This function is purely meant as a safeguard and you should use it for error checking. For example, the following can be found in the simple switch target constructor:
void bm::SwitchWContexts::block_until_no_more_packets | ( | ) |
void bm::SwitchWContexts::disable_config_swap | ( | ) |
Disable JSON config swapping for the switch.
int bm::SwitchWContexts::do_swap | ( | ) |
Performs a configuration swap if one was requested by the control plane. Returns 0
if a swap had indeed been requested, 1
otherwise. If a swap was requested, the method will prevent new Packet instances from being created and will block until all existing instances have been destroyed. It will then perform the swap. Care should be taken when using this function, as it invalidates some pointers that your target may still be using. See switch.h documentation for more information.
void bm::SwitchWContexts::enable_config_swap | ( | ) |
Enable JSON config swapping for the switch.
|
inline |
Checks that the given field exists for context cxt_id
, i.e. checks that the field was defined in the input JSON used to configure that context.
void bm::SwitchWContexts::force_arith_field | ( | const std::string & | header_name, |
const std::string & | field_name | ||
) |
Force arithmetic on field. No effect if field is not defined in the input JSON. For optimization reasons, only fields on which arithmetic will be performed receive the ability to perform arithmetic operations. These special fields are determined by analyzing the P4 program / the JSON input. For example, if a field is used in a primitive action call, arithmetic will be automatically enabled for this field in bmv2. Calling Field::get() on a Field instance for which arithmetic has not been abled will result in a segfault or an assert. If your target needs to enable arithmetic on a field for which arithmetic was not automatically enabled (could happen in some rare cases), you can enable it manually by calling this method.
void bm::SwitchWContexts::force_arith_header | ( | const std::string & | header_name | ) |
Force arithmetic on all the fields of header header_name
. No effect if the header is not defined in the input JSON. Is equivalent to calling force_arith_field() on all fields in the header. See force_arith_field() for more information.
|
inline |
Retrieve the shared pointer to an object of type T
previously added to the switch using add_component().
|
inline |
Return string-to-string map of the target-specific options included in the input config JSON for a given context.
|
inline |
Access a Context by context id, throws a std::out_of_range exception if cxt_id
is invalid.
|
inline |
Retrieve the shared pointer to an object of type T
previously added to one of the switch contexts using add_cxt_component().
|
inline |
Returns the device id for this switch instance.
|
inline |
Return a copy of the error codes map (a bi-directional map between an error code's integral value and its name / description) for a given context.
|
inline |
Obtain a pointer to the LearnEngine for a given Context.
|
inline |
Get the number of contexts included in this switch.
|
inline |
Returns the nanomsg IPC address for this switch.
|
inline |
Returns the Thrift port used for the runtime RPC server.
int bm::SwitchWContexts::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 |
||
) |
Initialize the switch using command line options. This function is meant to be called right after your switch instance has been constructed. For example, in the case of the standard simple switch target:
If your target has custom CLI options, you can provide a pointer tp
to a secondary parser which implements the TargetParserIface interface. The bm::TargetParserIface::parse method will be called with the unrecognized options. Target specific options need to appear after bmv2 general options on the command line, and be separated from them by --
. For example:
If you wish to use your own TransportIface implementation for notifications instead of the default nanomsg one, you can provide one. Similarly if you want to provide your own DevMgrIface implementation for packet I/O, you can do so. Note that even when using your own DevMgrIface implementation, you can still use the --interface
(or -i
) command-line option; we will call port_add on your implementation appropriately.
int bm::SwitchWContexts::init_from_options_parser | ( | const OptionsParser & | parser, |
std::shared_ptr< TransportIface > | my_transport = nullptr , |
||
std::unique_ptr< DevMgrIface > | my_dev_mgr = nullptr |
||
) |
Initialize the switch using an bm::OptionsParser instance. This is similar to init_from_command_line_options() but the target is responsible for parsing the command-line options itself. In other words, the target needs to instantiate a bm::OptionsParser object, invoke bm::OptionsParser::parse() on it and pass the object to this method as parser
. This is useful if the target needs to access some of the command-line options before initializing the switch. For example, the target may want to use a custom bm::DevMgrIface implementation and may need some information from the command-line to instantiate it.
Packet bm::SwitchWContexts::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
.
std::unique_ptr<Packet> bm::SwitchWContexts::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
.
|
privatepure virtual |
Override in your switch implementation; it will be called every time a packet is received.
|
inlineprivatevirtual |
You can override this method in your target. It will be called whenever reset_state() is invoked by the control plane. For example, the simple_switch target uses this to reset PRE state.
bool bm::SwitchWContexts::set_group_selector | ( | cxt_id_t | cxt_id, |
const std::string & | act_prof_name, | ||
std::shared_ptr< ActionProfile::GroupSelectionIface > | selector | ||
) |
Use a custom GroupSelectionIface implementation for dataplane member selection for action profile with name action_profile_name
. Returns false in case of failure (if the action profile name is not valid).
void bm::SwitchWContexts::start_and_return | ( | ) |
Call this function when you are ready to process packets. This function will call start_and_return_() which you have to override in your switch implementation. Note that if the switch is started without a P4 configuration, this function will block until a P4 configuration is available (you can push a configuration through the Thrift RPC service) before calling start_and_return_().
|
privatepure virtual |
Override in your switch implementation; do all your initialization in this function (e.g. start processing threads) and call start_and_return() when you are ready to process packets. See start_and_return() for more information.
|
inlineprivatevirtual |
You can override this method in your target. It will be called at the end of a config swap operation. At that time, you will be guaranteed that no Packet instances exist, as long as your target uses the correct methods to instantiate these objects (bm::SwitchWContexts::new_packet_ptr() and bm::SwitchWContexts::new_packet()).
int bm::SwitchWContexts::swap_requested | ( | ) |
Returns true if a configuration swap was requested by the control plane. See switch.h documentation for more information.