Skip to content

Commit

Permalink
Merge pull request #298 from FedeParola/overhead
Browse files Browse the repository at this point in the history
Reduce Polycube overhead
  • Loading branch information
frisso committed May 19, 2020
2 parents fc7cbbc + 20cee03 commit 83b4a6d
Show file tree
Hide file tree
Showing 34 changed files with 585 additions and 472 deletions.
5 changes: 3 additions & 2 deletions src/libs/polycube/include/polycube/services/cube_iface.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ class CubeIface : virtual public BaseCubeIface {
virtual void remove_port(const std::string &name) = 0;
virtual std::shared_ptr<PortIface> get_port(const std::string &name) = 0;

virtual void update_forwarding_table(int index, int value) = 0;
virtual void update_forwarding_table(uint16_t port, uint32_t next,
bool is_netdev) = 0;

virtual void set_conf(const nlohmann::json &conf) = 0;
virtual nlohmann::json to_json() const = 0;
Expand All @@ -98,7 +99,7 @@ class CubeIface : virtual public BaseCubeIface {

class TransparentCubeIface : virtual public BaseCubeIface {
public:
virtual void set_next(uint32_t next, ProgramType type) = 0;
virtual void set_next(uint16_t next, ProgramType type, bool is_netdev) = 0;
virtual void set_parameter(const std::string &parameter,
const std::string &value) = 0;
virtual void send_packet_out(const std::vector<uint8_t> &packet, Direction direction,
Expand Down
83 changes: 46 additions & 37 deletions src/polycubed/src/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ BPF_TABLE("extern", int, int, nodes, _POLYCUBE_MAX_NODES);
struct metadata {
u16 module_index;
u8 is_netdev;
u16 port_id;
u32 flags;
};
u32 flags;
} __attribute__((packed));
BPF_TABLE("array", u32, struct metadata, md_map_rx, MD_MAP_SIZE);
BPF_TABLE("array", u32, u32, index_map_rx, 1);
Expand Down Expand Up @@ -93,18 +94,21 @@ int controller_module_rx(struct __sk_buff *ctx) {
u16 in_port = md->port_id;
u16 module_index = md->module_index;
u32 flags = md->flags;
u8 is_netdev = md->is_netdev;
u32 flags = md->flags;
ctx->cb[0] = in_port << 16 | module_index;
ctx->cb[2] = flags;
if (module_index == 0xffff) {
pcn_log(ctx, LOG_INFO, "[tc-decapsulator]: NH is stack, flags: 0x%x", flags);
if (flags & MD_EGRESS_CONTEXT) {
return bpf_redirect(in_port, 0);
} else {
return 0;
}
ctx->cb[2] = flags;
if (is_netdev) {
return bpf_redirect(module_index, 0);
} else if (module_index == 0xffff) {
pcn_log(ctx, LOG_INFO, "[tc-decapsulator]: NH is stack, flags: 0x%x", flags);
if (flags & MD_EGRESS_CONTEXT) {
return bpf_redirect(in_port, 0);
} else {
return 0;
}
}
nodes.call(ctx, module_index);
pcn_log(ctx, LOG_ERR, "[tc-decapsulator]: 'nodes.call'. Module is: %d", module_index);
Expand All @@ -114,18 +118,14 @@ int controller_module_rx(struct __sk_buff *ctx) {

// Receives packet from controller and forwards it to the CubeXDP
const std::string CTRL_XDP_RX = R"(
#include <bcc/helpers.h>
#include <bcc/proto.h>
#include <uapi/linux/bpf.h>
#include <uapi/linux/if_ether.h>
#include <linux/string.h>
#include <linux/rcupdate.h>
struct xdp_metadata {
u16 module_index;
u8 is_netdev;
u16 port_id;
};
} __attribute__((packed));
struct pkt_metadata {
u16 module_index;
Expand All @@ -145,14 +145,17 @@ BPF_TABLE("array", u32, u32, xdp_index_map_rx, 1);
int controller_module_rx(struct xdp_md *ctx) {
pcn_log(ctx, LOG_TRACE, "[xdp-decapsulator]: from controller");
u32 key = 0;
struct pkt_metadata xdp_md = {0};
int zero = 0;
struct pkt_metadata *md = port_md.lookup(&zero);
if (!md) {
return XDP_ABORTED;
}
u32 zero = 0;
u32 *index = xdp_index_map_rx.lookup(&zero);
if (!index) {
pcn_log(ctx, LOG_ERR, "[xdp-decapsulator]: !index");
return XDP_DROP;
return XDP_ABORTED;
}
rcu_read_lock();
Expand All @@ -163,24 +166,27 @@ int controller_module_rx(struct xdp_md *ctx) {
u32 i = *index;
struct xdp_metadata *md = md_map_rx.lookup(&i);
if (!md) {
pcn_log(ctx, LOG_ERR, "[xdp-decapsulator]: !md");
return XDP_DROP;
struct xdp_metadata *xdp_md = md_map_rx.lookup(&i);
if (!xdp_md) {
pcn_log(ctx, LOG_ERR, "[xdp-decapsulator]: !xdp_md");
return XDP_ABORTED;
}
xdp_md.in_port = md->port_id;
xdp_md.module_index = md->module_index;
port_md.update(&key, &xdp_md);
// Initialize metadata
md->in_port = xdp_md->port_id;
md->packet_len = ctx->data_end - ctx->data;
md->traffic_class = 0;
memset(md->md, 0, sizeof(md->md));
if (xdp_md.module_index == 0xffff) {
if (xdp_md->is_netdev) {
return bpf_redirect(xdp_md->module_index, 0);
} else if (xdp_md->module_index == 0xffff) {
pcn_log(ctx, LOG_INFO, "[xdp-decapsulator]: NH is stack");
return XDP_PASS;
} else {
xdp_nodes.call(ctx, xdp_md.module_index);
pcn_log(ctx, LOG_ERR, "[xdp-decapsulator]: 'xdp_nodes.call'. Module is: %d", xdp_md.module_index);
return XDP_DROP;
xdp_nodes.call(ctx, xdp_md->module_index);
pcn_log(ctx, LOG_ERR, "[xdp-decapsulator]: 'xdp_nodes.call'. Module is: %d", xdp_md->module_index);
return XDP_ABORTED;
}
}
)";
Expand Down Expand Up @@ -324,13 +330,16 @@ void Controller::unregister_cb(int id) {
}

// caller must guarantee that module_index and port_id are valid
void Controller::send_packet_to_cube(uint16_t module_index, uint16_t port_id,
void Controller::send_packet_to_cube(uint16_t module_index, bool is_netdev,
uint16_t port_id,
const std::vector<uint8_t> &packet,
service::Direction direction, bool mac_overwrite) {
service::Direction direction,
bool mac_overwrite) {
ctrl_rx_md_index_++;
ctrl_rx_md_index_ %= MD_MAP_SIZE;

metadata md_temp = {module_index, port_id, MD_PKT_FROM_CONTROLLER};
metadata md_temp = {module_index, (uint8_t)int(is_netdev), port_id,
MD_PKT_FROM_CONTROLLER};
if (direction == service::Direction::EGRESS) {
md_temp.flags |= MD_EGRESS_CONTEXT;
}
Expand Down
10 changes: 6 additions & 4 deletions src/polycubed/src/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace polycubed {
// struct used when sending a packet to an cube
struct __attribute__((__packed__)) metadata {
uint16_t module_index;
uint8_t is_netdev;
uint16_t port_id;

#define MD_PKT_FROM_CONTROLLER (1UL << 0)
Expand All @@ -66,10 +67,11 @@ class Controller {

void register_cb(int id, const packet_in_cb &cb);
void unregister_cb(int id);
void send_packet_to_cube(uint16_t module_index, uint16_t port_id,
const std::vector<uint8_t> &packet,
service::Direction direction=service::Direction::INGRESS,
bool mac_overwrite=false);
void send_packet_to_cube(
uint16_t module_index, bool is_netdev, uint16_t port_id,
const std::vector<uint8_t> &packet,
service::Direction direction=service::Direction::INGRESS,
bool mac_overwrite=false);

int get_fd() const;
uint32_t get_id() const;
Expand Down
39 changes: 20 additions & 19 deletions src/polycubed/src/cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,9 @@ Cube::Cube(const std::string &name, const std::string &service_name,
span_(span) {
std::lock_guard<std::mutex> guard(bcc_mutex);

auto forward_ = master_program_->get_array_table<uint32_t>("forward_chain_");
forward_chain_ = std::unique_ptr<ebpf::BPFArrayTable<uint32_t>>(
new ebpf::BPFArrayTable<uint32_t>(forward_));

auto egress_next = master_program_->get_array_table<uint32_t>("egress_next");
egress_next_ = std::unique_ptr<ebpf::BPFArrayTable<uint32_t>>(
new ebpf::BPFArrayTable<uint32_t>(egress_next));
auto egress_next = master_program_->get_array_table<uint16_t>("egress_next");
egress_next_ = std::unique_ptr<ebpf::BPFArrayTable<uint16_t>>(
new ebpf::BPFArrayTable<uint16_t>(egress_next));

// add free ports
for (uint16_t i = 0; i < _POLYCUBE_MAX_PORTS; i++)
Expand Down Expand Up @@ -278,13 +274,19 @@ std::map<std::string, std::shared_ptr<PortIface>> &Cube::get_ports() {
return ports_by_name_;
}

void Cube::update_forwarding_table(int index, int value) {
void Cube::update_forwarding_table(uint16_t port, uint32_t next,
bool is_netdev) {
std::lock_guard<std::mutex> cube_guard(cube_mutex_);
if (forward_chain_) // is the forward chain still active?
forward_chain_->update_value(index, value);
if (next != 0) {
forward_chain_[port] = std::make_pair(next, is_netdev);
} else {
forward_chain_.erase(port);
}
cube_mutex_.unlock();
reload_all();
}

void Cube::set_egress_next(int port, uint32_t index) {
void Cube::set_egress_next(int port, uint16_t index) {
egress_next_->update_value(port, index);
}

Expand Down Expand Up @@ -315,20 +317,19 @@ const std::string Cube::get_veth_name_from_index(const int ifindex) {
}

const std::string Cube::MASTER_CODE = R"(
// table used to save ports to endpoint relation
BPF_TABLE_SHARED("array", int, u32, forward_chain_, _POLYCUBE_MAX_PORTS);
// Table used to store, for every port, the potential index of the program to
// call after the egress program.
// The higher 16 bits are reserved for XDP programs, if they are set they
// override the value of the lower 16 bits.
BPF_TABLE_SHARED("array", int, u32, egress_next, _POLYCUBE_MAX_PORTS);
BPF_TABLE_SHARED("array", int, u16, egress_next, _POLYCUBE_MAX_PORTS);
// Same as above for XDP programs. Higher 16 bits of the value tells if the next
// entity is a program (0) or a netdev (1). Lower 16 bits contain its index.
BPF_TABLE_SHARED("array", int, u32, egress_next_xdp, _POLYCUBE_MAX_PORTS);
)";

const std::string Cube::CUBE_WRAPPER = R"(
BPF_TABLE("extern", int, u32, forward_chain_, _POLYCUBE_MAX_PORTS);
#if POLYCUBE_PROGRAM_TYPE == 1 // EGRESS
BPF_TABLE("extern", int, u32, egress_next, _POLYCUBE_MAX_PORTS);
BPF_TABLE("extern", int, u16, egress_next, _POLYCUBE_MAX_PORTS);
BPF_TABLE("extern", int, u32, egress_next_xdp, _POLYCUBE_MAX_PORTS);
#endif
)";

Expand Down
10 changes: 4 additions & 6 deletions src/polycubed/src/cube.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,11 @@ class Cube : public BaseCube, public CubeIface {
std::shared_ptr<PortIface> get_port(const std::string &name);
std::map<std::string, std::shared_ptr<PortIface>> &get_ports();

void update_forwarding_table(int index, int value);
void update_forwarding_table(uint16_t port, uint32_t next, bool is_netdev);

// Sets the index of the next program to call after the egress program of this
// cube is executed.
// The higher 16 bits are reserved for XDP programs, if they are set they
// override the value of the lower 16 bits.
void set_egress_next(int port, uint32_t index);
virtual void set_egress_next(int port, uint16_t index);

void set_conf(const nlohmann::json &conf);
nlohmann::json to_json() const;
Expand All @@ -84,11 +82,11 @@ class Cube : public BaseCube, public CubeIface {
uint16_t allocate_port_id();
void release_port_id(uint16_t id);

std::unique_ptr<ebpf::BPFArrayTable<uint32_t>> forward_chain_;
std::unique_ptr<ebpf::BPFArrayTable<uint32_t>> egress_next_;
std::unique_ptr<ebpf::BPFArrayTable<uint16_t>> egress_next_;

std::map<std::string, std::shared_ptr<PortIface>> ports_by_name_;
std::map<int, std::shared_ptr<PortIface>> ports_by_index_;
std::map<uint16_t, std::pair<uint32_t, bool>> forward_chain_;
std::set<uint16_t> free_ports_; // keeps track of available ports

std::map<std::string, std::shared_ptr<Veth>> veth_by_name_;
Expand Down
43 changes: 33 additions & 10 deletions src/polycubed/src/cube_tc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "datapath_log.h"
#include "exceptions.h"
#include "patchpanel.h"
#include "utils/utils.h"

#include <iostream>

Expand Down Expand Up @@ -56,10 +57,33 @@ std::string CubeTC::get_wrapper_code() {
CUBETC_HELPERS;
}

std::string CubeTC::get_redirect_code() {
std::stringstream ss;

for(auto const& [index, val] : forward_chain_) {
ss << "case " << index << ":\n";
ss << "skb->cb[0] = " << val.first << ";\n";

if (val.second) {
// It is a net interface
ss << "return bpf_redirect(" << (val.first & 0xffff) << ", 0);\n";
} else {
ss << "nodes.call(skb, " << (val.first & 0xffff) << ");\n";
}

ss << "break;\n";
}

return ss.str();
}

void CubeTC::do_compile(int id, ProgramType type, LogLevel level_,
ebpf::BPF &bpf, const std::string &code, int index, bool shadow, bool span) {
std::string wrapper_code = get_wrapper_code();
utils::replaceStrAll(wrapper_code, "_REDIRECT_CODE", get_redirect_code());

// compile ebpf program
std::string all_code(get_wrapper_code() +
std::string all_code(wrapper_code +
DatapathLog::get_instance().parse_log(code));

std::vector<std::string> cflags(cflags_);
Expand Down Expand Up @@ -305,13 +329,10 @@ int pcn_vlan_push_tag(struct CTXTYPE *ctx, u16 eth_proto, u32 vlan_id) {
const std::string CubeTC::CUBETC_WRAPPER = R"(
static __always_inline
int forward(struct CTXTYPE *skb, u32 out_port) {
u32 *next = forward_chain_.lookup(&out_port);
if (next) {
skb->cb[0] = *next;
//bpf_trace_printk("fwd: port: %d, next: 0x%x\n", out_port, *next);
nodes.call(skb, *next & 0xffff);
switch (out_port) {
_REDIRECT_CODE;
}
//bpf_trace_printk("fwd:%d=0\n", out_port);
return TC_ACT_SHOT;
}
Expand Down Expand Up @@ -367,17 +388,17 @@ int handle_rx_wrapper(struct CTXTYPE *skb) {
// pass
int port = md.in_port;
u32 *next = egress_next.lookup(&port);
u16 *next = egress_next.lookup(&port);
if (!next) {
return TC_ACT_SHOT;
}
if (*next == 0) {
return TC_ACT_SHOT;
} else if ((*next & 0xffff) == 0xffff) {
} else if (*next == 0xffff) {
return TC_ACT_OK;
} else {
nodes.call(skb, *next & 0xffff);
nodes.call(skb, *next);
}
#else // INGRESS
Expand All @@ -388,6 +409,7 @@ int handle_rx_wrapper(struct CTXTYPE *skb) {
return TC_ACT_SHOT;
}
#if POLYCUBE_PROGRAM_TYPE == 0 // Only INGRESS programs can redirect
static __always_inline
int pcn_pkt_redirect(struct CTXTYPE *skb,
struct pkt_metadata *md, u32 port) {
Expand All @@ -399,6 +421,7 @@ int pcn_pkt_redirect(struct CTXTYPE *skb,
#endif
return RX_REDIRECT;
}
#endif
static __always_inline
int pcn_pkt_redirect_ns(struct CTXTYPE *skb,
Expand Down

0 comments on commit 83b4a6d

Please sign in to comment.