Writing the control plane¶
Handling eBPF programs¶
A cube is composed by 0 or more eBPF programs, the master program is the first that receives the packets to be processed.
The polycube::service::Cube
and the polycube::service::TransparentCube
classes provide wrapper to manage eBPF programs, it allows to load, unload and reload them.
The constructor of such classes receives two std::vector<std::string>
that contains the code for the ingress and egress chain programs, those programs will be compiled and loaded when the cube is created, this is possible to create a Cube
without any program and add them later on.
The following functions allow to reload, add and delete eBPF programs.
void reload(const std::string &code, int index, ProgramType type)
int add_program(const std::string &code, int index, ProgramType type)
void del_program(int index, ProgramType type)
Where:
index: position of the program
type: if the program is on the
INGRESS
orEGRESS
chain.
Adding and removing ports¶
The main service class has two methods, addPorts
and removePorts
, these methods are automatically called by the infrastructure.
Within these functions, there must be a call to Cube::add_port()
and Cube::remove_port()
respectively, these functions allow the infrastructure to perform all the required work for adding or removing the port.
The Cube::add_port
function receives a PortsJsonObject
object with the initial port configuration.
The stub generated already include those functions, so in general the developer does not have to worry about it.
eBPF maps API¶
The polycube::service::BaseCube
base class provides the get_{raw, array, percpuarray, hash, percpuhash}_table()
methods that allows to get a reference to an eBPF map.
The RawTable
is intended to access the memory of the maps without any formatting, the user should pass pointers to key and/or value buffers.
It provides the following API:
void set(const void* key, const void* value)
void get(const void* key, void * value)
void remove(const void* key)
The ArrayTable
and PercpuArrayTable
are intended to handle array like maps, this class is templated on the value type.
The ArrayTable
provides the following API:
void set(const uint32_t &key, const ValueType &value)
ValueType get(const uint32_t &key)
std::vector<std::pair<uint32_t, std::vector<ValueType>>> get_all()
The the PercpuArrayTable
provides:
std::vector<ValueType> get(const uint32_t &key)
std::vector<std::pair<uint32_t, std::vector<ValueType>>> get_all()
void set(const uint32_t &key, const std::vector<ValueType> &value)
void set(const uint32_t &key, const ValueType &value): Set value in all CPUs.
The HashTable
and PercpuHashTable
are intended to handle hash like maps, this class is templated on the key and value type.
The HashTable
provides the following API:
ValueType get(const KeyType &key)
std::vector<std::pair<KeyType, ValueType>> get_all()
void set(const KeyType &key, const ValueType &value)
void remove(const KeyType &key)
void remove_all()
The PercpuHashTable
exposes:
std::vector<ValueType> get(const KeyType &key)
std::vector<std::pair<KeyType, std::vector<ValueType>>> get_all()
void set(const KeyType &key, const std::vector<ValueType> &value)
void set(const KeyType &key, const ValueType &value)**: Set value in all CPUs.
void remove(const KeyType &key)
void remove_all()
In order to have an idea of how to implement this, take at look at the already implemented services, router and firewall are good examples.
Implementing the control path¶
Handling PacketIn events¶
- If the service is intended to receive data packets in the control path (using an approach that is commonly said slow path), you should implement the logic that handles those packets in the packet_in function, it receives:
port: a reference to the ingress port of the packet
md: the metadata associated to this packet
reason and metadata: values used by the datapath when sending the packet to the control path through the
pcn_pkt_controller()
functions.packet: an array containing the packet’s bytes.
Generating PacketOut events¶
The Port
class contains the send_packet_out(EthernetII &packet, bool recirculate = false)
method that allows to inject packets into the datapath.
The recirculate
parameter specifies if the packet should be sent out of the port (recirculate = false
) or received through the port (recirculate = true
).
Only in shadow services the Port
class contains the send_packet_ns(EthernetII &packet)
method that allows to send packets into the service namespace.
A reference to a port can be got using the get_port()
function of the Cube base class.
Debugging the control plane¶
See how to debug by logging in the control plane.