bmv2
Designing your own switch target with bmv2
Public Member Functions | Protected Member Functions | Private Member Functions | List of all members
bm::SwitchWContexts Class Referenceabstract
Inheritance diagram for bm::SwitchWContexts:
Inheritance graph
[legend]

Public Member Functions

 SwitchWContexts (size_t nb_cxts=1u, bool enable_swap=false)
 
Contextget_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< Packetnew_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...
 
LearnEngineIfaceget_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
 
- Public Member Functions inherited from bm::DevMgr
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

- Public Types inherited from bm::DevMgr
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...
 

Detailed Description

Base class for a switch implemenattion where multi-context support is required.

Constructor & Destructor Documentation

◆ SwitchWContexts()

bm::SwitchWContexts::SwitchWContexts ( size_t  nb_cxts = 1u,
bool  enable_swap = false 
)
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.

Member Function Documentation

◆ add_component()

template<typename T >
bool bm::SwitchWContexts::add_component ( std::shared_ptr< T >  ptr)
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().

◆ add_cxt_component()

template<typename T >
bool bm::SwitchWContexts::add_cxt_component ( cxt_id_t  cxt_id,
std::shared_ptr< T >  ptr 
)
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().

◆ add_required_field()

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:

add_required_field("standard_metadata", "ingress_port");
add_required_field("standard_metadata", "packet_length");
add_required_field("standard_metadata", "instance_type");
add_required_field("standard_metadata", "egress_spec");
add_required_field("standard_metadata", "egress_port");

◆ block_until_no_more_packets()

void bm::SwitchWContexts::block_until_no_more_packets ( )

Utility function which prevents new Packet instances from being created and blocks until all existing Packet instances have been destroyed in all contexts

◆ disable_config_swap()

void bm::SwitchWContexts::disable_config_swap ( )

Disable JSON config swapping for the switch.

◆ do_swap()

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.

◆ enable_config_swap()

void bm::SwitchWContexts::enable_config_swap ( )

Enable JSON config swapping for the switch.

◆ field_exists()

bool bm::SwitchWContexts::field_exists ( cxt_id_t  cxt_id,
const std::string &  header_name,
const std::string &  field_name 
) const
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.

◆ force_arith_field()

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.

◆ force_arith_header()

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.

◆ get_component()

template<typename T >
std::shared_ptr<T> bm::SwitchWContexts::get_component ( )
inline

Retrieve the shared pointer to an object of type T previously added to the switch using add_component().

◆ get_config_options()

ConfigOptionMap bm::SwitchWContexts::get_config_options ( cxt_id_t  cxt_id) const
inline

Return string-to-string map of the target-specific options included in the input config JSON for a given context.

◆ get_context()

Context* bm::SwitchWContexts::get_context ( cxt_id_t  cxt_id = 0u)
inline

Access a Context by context id, throws a std::out_of_range exception if cxt_id is invalid.

◆ get_cxt_component()

template<typename T >
std::shared_ptr<T> bm::SwitchWContexts::get_cxt_component ( cxt_id_t  cxt_id)
inline

Retrieve the shared pointer to an object of type T previously added to one of the switch contexts using add_cxt_component().

◆ get_device_id()

device_id_t bm::SwitchWContexts::get_device_id ( ) const
inline

Returns the device id for this switch instance.

◆ get_error_codes()

ErrorCodeMap bm::SwitchWContexts::get_error_codes ( cxt_id_t  cxt_id) const
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.

◆ get_learn_engine()

LearnEngineIface* bm::SwitchWContexts::get_learn_engine ( cxt_id_t  cxt_id)
inline

Obtain a pointer to the LearnEngine for a given Context.

◆ get_nb_cxts()

size_t bm::SwitchWContexts::get_nb_cxts ( )
inline

Get the number of contexts included in this switch.

◆ get_notifications_addr()

std::string bm::SwitchWContexts::get_notifications_addr ( ) const
inline

Returns the nanomsg IPC address for this switch.

◆ get_runtime_port()

int bm::SwitchWContexts::get_runtime_port ( ) const
inline

Returns the Thrift port used for the runtime RPC server.

◆ init_from_command_line_options()

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:

simple_switch = new SimpleSwitch();
int status = simple_switch->init_from_command_line_options(argc, argv);
if (status != 0) std::exit(status);

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:

<my_target_exe> prog.json -i 0@eth0 -- --my-option v

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.

◆ init_from_options_parser()

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.

◆ new_packet()

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.

◆ new_packet_ptr()

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.

◆ receive_()

virtual int bm::SwitchWContexts::receive_ ( port_t  port_num,
const char *  buffer,
int  len 
)
privatepure virtual

Override in your switch implementation; it will be called every time a packet is received.

◆ reset_target_state_()

virtual void bm::SwitchWContexts::reset_target_state_ ( )
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.

◆ set_group_selector()

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).

◆ start_and_return()

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_().

◆ start_and_return_()

virtual void bm::SwitchWContexts::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.

◆ swap_notify_()

virtual void bm::SwitchWContexts::swap_notify_ ( )
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()).

◆ swap_requested()

int bm::SwitchWContexts::swap_requested ( )

Returns true if a configuration swap was requested by the control plane. See switch.h documentation for more information.


The documentation for this class was generated from the following file:
bm::SwitchWContexts::add_required_field
void add_required_field(const std::string &header_name, const std::string &field_name)