Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions src/services/pcn-simplebridge/src/FdbEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ FdbEntry::FdbEntry(Fdb &parent, const FdbEntryJsonObject &conf): parent_(parent)
logger()->info("Creating FdbEntry instance");
}

FdbEntry::FdbEntry(Fdb &parent, const std::string &address, uint64_t entry_age, uint32_t out_port) :
FdbEntry::FdbEntry(Fdb &parent, const std::string &address, uint32_t entry_age, uint32_t out_port) :
parent_(parent), address_(address), entry_age_(entry_age), port_no_(out_port)
{
auto port = parent.parent_.get_port(port_no_);
Expand Down Expand Up @@ -74,12 +74,10 @@ void FdbEntry::create(Fdb &parent, const std::string &address, const FdbEntryJso

struct timespec now_timespec;
clock_gettime(CLOCK_MONOTONIC, &now_timespec);
const uint64_t SEC2NANOSEC = 1000000000ULL;
uint64_t now = now_timespec.tv_sec*SEC2NANOSEC + now_timespec.tv_nsec;

uint64_t key = utils::mac_string_to_be_uint(address);
fwd_entry value {
.timestamp = now,
.timestamp = (uint32_t) now_timespec.tv_sec,
.port = port_index,
};

Expand All @@ -97,22 +95,21 @@ std::shared_ptr<FdbEntry> FdbEntry::constructFromMap(Fdb &parent, const std::str
const fwd_entry &value) {
struct timespec now_timespec;
clock_gettime(CLOCK_MONOTONIC, &now_timespec);
const uint64_t SEC2NANOSEC = 1000000000ULL;
uint64_t now = now_timespec.tv_sec*SEC2NANOSEC + now_timespec.tv_nsec;
uint32_t now = now_timespec.tv_sec;

uint64_t key = utils::mac_string_to_be_uint(address);
uint64_t timestamp = value.timestamp;
uint32_t timestamp = value.timestamp;

//Here I'm going to check if the entry in the filtering database is too old.\
//In this case, I'll not show the entry
if ((now - timestamp) > parent.getAgingTime()*SEC2NANOSEC) {
if ((now - timestamp) > parent.getAgingTime()) {
parent.logger()->debug("Ignoring old entry: now {0}, last_seen: {1}",
now/SEC2NANOSEC, timestamp/SEC2NANOSEC);
now, timestamp);
auto fwdtable = parent.parent_.get_hash_table<uint64_t, fwd_entry>("fwdtable");
fwdtable.remove(key);
return nullptr;
}
uint64_t entry_age = (now - timestamp)/SEC2NANOSEC;
uint32_t entry_age = now - timestamp;
uint32_t port_no = value.port;
return std::make_shared<FdbEntry>(parent, address, entry_age, port_no);
}
Expand Down
6 changes: 3 additions & 3 deletions src/services/pcn-simplebridge/src/FdbEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Fdb;

/* definitions copied from datapath */
struct fwd_entry {
uint64_t timestamp;
uint32_t timestamp;
uint32_t port;
} __attribute__((packed));

Expand All @@ -36,7 +36,7 @@ using namespace io::swagger::server::model;
class FdbEntry : public FdbEntryInterface {
public:
FdbEntry(Fdb &parent, const FdbEntryJsonObject &conf);
FdbEntry(Fdb &parent, const std::string &address, uint64_t entry_age, uint32_t out_port);
FdbEntry(Fdb &parent, const std::string &address, uint32_t entry_age, uint32_t out_port);
virtual ~FdbEntry();

static void create(Fdb &parent, const std::string &address, const FdbEntryJsonObject &conf);
Expand Down Expand Up @@ -77,7 +77,7 @@ class FdbEntry : public FdbEntryInterface {

std::string address_;
std::string port_name_;
uint64_t entry_age_;
uint32_t entry_age_;
uint32_t port_no_;
};

37 changes: 35 additions & 2 deletions src/services/pcn-simplebridge/src/Simplebridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,57 @@

#include <tins/ethernetII.h>
#include <tins/tins.h>
#include <thread>

using namespace Tins;

Simplebridge::Simplebridge(const std::string name, const SimplebridgeJsonObject &conf, CubeType type)
: Cube(name, {generate_code()}, {}, type, conf.getPolycubeLoglevel()) {
: Cube(name, {generate_code()}, {}, type, conf.getPolycubeLoglevel()),
quit_thread_(false) {
logger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [Simplebridge] [%n] [%l] %v");
logger()->info("Creating Simplebridge instance");

addFdb(conf.getFdb());
addPortsList(conf.getPorts());

timestamp_update_thread_ = std::thread(&Simplebridge::updateTimestampTimer, this);
}

Simplebridge::~Simplebridge() {
// we are destroying this service, prepare for it.
quitAndJoin();
Cube::dismount();
}

void Simplebridge::quitAndJoin() {
quit_thread_ = true;
timestamp_update_thread_.join();
}

void Simplebridge::updateTimestampTimer() {
do {
sleep(1);
updateTimestamp();
} while (!quit_thread_);
}

/*
* This method is in charge of updating the timestamp table
* that is used in the dataplane to avoid calling the bpf_ktime helper
* that introduces a non-negligible overhead to the eBPF program.
*/
void Simplebridge::updateTimestamp() {
try {
// get timestamp from system
struct timespec now_timespec;
clock_gettime(CLOCK_MONOTONIC, &now_timespec);
auto timestamp_table = get_array_table<uint32_t>("timestamp");
timestamp_table.set(0, now_timespec.tv_sec);
} catch (...) {
logger()->error("Error while updating the timestamp table");
}
}

void Simplebridge::update(const SimplebridgeJsonObject &conf) {
//This method updates all the object/parameter in Simplebridge object specified in the conf JsonObject.
//You can modify this implementation.
Expand Down Expand Up @@ -141,4 +175,3 @@ void Simplebridge::reloadCodeWithAgingtime(uint32_t aging_time) {




8 changes: 8 additions & 0 deletions src/services/pcn-simplebridge/src/Simplebridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "polycube/services/utils.h"

#include <spdlog/spdlog.h>
#include <thread>

#include "Fdb.h"
#include "Ports.h"
Expand Down Expand Up @@ -96,6 +97,13 @@ class Simplebridge : public polycube::service::Cube<Ports>, public SimplebridgeI
std::unordered_map<std::string, Ports> ports_;
std::shared_ptr<Fdb> fdb_ = nullptr;

void updateTimestamp();
void updateTimestampTimer();
void quitAndJoin();

std::thread timestamp_update_thread_;
std::atomic<bool> quit_thread_;

void flood_packet(Port &port, PacketInMetadata &md, const std::vector<uint8_t> &packet);
std::mutex ports_mutex_;
};
Expand Down
45 changes: 26 additions & 19 deletions src/services/pcn-simplebridge/src/Simplebridge_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,28 @@
#define REASON_FLOODING 0x01

struct fwd_entry {
u64 timestamp;
u32 timestamp;
u32 port;
} __attribute__((packed));
} __attribute__((packed, aligned(8)));

BPF_TABLE("hash", __be64, struct fwd_entry, fwdtable, 1024);
BPF_TABLE("array", int, uint32_t, timestamp, 1);

struct eth_hdr {
__be64 dst:48;
__be64 src:48;
__be16 proto;
} __attribute__((packed));

static __always_inline u32 time_get_sec() {
int key = 0;
u32 *ts = timestamp.lookup(&key);
if (ts)
return *ts;

return 0;
}

static __always_inline
int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
void *data = (void *)(long)ctx->data;
Expand All @@ -60,22 +70,27 @@ int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {

// LEARNING PHASE
__be64 src_key = eth->src;
u64 now = bpf_ktime_get_ns();
u32 now = time_get_sec();

struct fwd_entry e; // used to update the entry in the fdb
struct fwd_entry *entry = fwdtable.lookup(&src_key);

e.timestamp = now;
e.port = in_ifc;
if (!entry) {
struct fwd_entry e; // used to update the entry in the fdb

// Updating the timestamp associated to this entry in the fdb
fwdtable.update(&src_key, &e);
e.timestamp = now;
e.port = in_ifc;

pcn_log(ctx, LOG_TRACE, "MAC: %M learned (or timestamp updated)", src_key);
fwdtable.update(&src_key, &e);
pcn_log(ctx, LOG_TRACE, "MAC: %M learned", src_key);
} else {
entry->port = in_ifc;
entry->timestamp = now;
}

// FORWARDING PHASE: select interface(s) to send the packet
__be64 dst_mac = eth->dst;
// lookup in forwarding table fwdtable
struct fwd_entry *entry = fwdtable.lookup(&dst_mac);
entry = fwdtable.lookup(&dst_mac);
if (!entry) {
pcn_log(ctx, LOG_DEBUG, "Entry not found for dst-mac: %M", dst_mac);
goto DO_FLOODING;
Expand All @@ -84,15 +99,7 @@ int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
u64 timestamp = entry->timestamp;

// Check if the entry is still valid (not too old)
// Warning: the bpf_ktime_get_ns() used before is not monotonic and it may return
// a value that is older than a previously returned value. So, we have to add
// the very strange check 'now < timestamp' to handle this special case
if (now < timestamp) {
pcn_log(ctx, LOG_TRACE, "Entry is valid (but 'now < timestamp'). FORWARDING");
goto FORWARD;
}

if ((now - timestamp) > FDB_TIMEOUT*1000000000ULL) {
if ((now - timestamp) > FDB_TIMEOUT) {
pcn_log(ctx, LOG_TRACE, "Entry is too old. FLOODING");
fwdtable.delete(&dst_mac);
goto DO_FLOODING;
Expand Down