Skip to content

Commit

Permalink
New implementation for retrieving timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardo committed Mar 5, 2020
1 parent f1b6d5c commit 864b5aa
Show file tree
Hide file tree
Showing 7 changed files with 383 additions and 386 deletions.
1 change: 1 addition & 0 deletions Documentation/polycubectl/polycubectl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Refer to :doc:`Quick Start <../quickstart>`.
pbforwarder service Policy-Based Forwarder Service
bridge service Bridge Service
nat service NAT Service
packetcapture service Packetcapture Service

connect command Connect ports
disconnect command Disconnect ports
Expand Down
75 changes: 47 additions & 28 deletions src/services/pcn-packetcapture/src/Packetcapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ Packetcapture::Packetcapture(const std::string name, const PacketcaptureJsonObje
PacketcaptureBase(name) {

/*
* The timestamp of the packet is acquired in the fast path using 'bpf_ktime_get_ns()'
* The timestamp of the packet is acquired in the fast path using:
* if BPF_PROG_TYPE_XDP is TC and ctx->tstamp != 0 we use ctx->tstamp
* it returns the current Unix epoch time
*
* otherwise if BPF_PROG_TYPE_XDP is not TC or ctx->tstamp == 0 we use 'bpf_ktime_get_ns()'
* This function returns the time elapsed since system booted, in nanoseconds.
* See line 59 in Packetcapture_dp_egress.c and Packetcapture_dp_ingress.c
*
* The packet's timestamp must be in epoch so now we will store the current
* time in epoch format and then the packet capture time offset,that was stored in the fast path,
Expand All @@ -54,7 +57,7 @@ Packetcapture::Packetcapture(const std::string name, const PacketcaptureJsonObje
* 'timeval struct ts' rapresents the system start time in epoch calculated as
* actual time - system uptime
*
* See line 164 of this file for more details
* See line 167 of this file for more details
*/


Expand Down Expand Up @@ -155,14 +158,17 @@ void Packetcapture::writeDump(const std::vector<uint8_t> &packet){
writeHeader = false;
}

/*
* Here the packet capture time offset must be added to the system boot time stored in epoch format.
* See line 61 of this file to see system boot time stored in epoch algorithm
*/

struct timeval tp;
std::chrono::system_clock::duration tp_dur = (timeP + temp_offset).time_since_epoch();
to_timeval(tp_dur, tp);
if (ts) {
/*
* Here the packet capture time offset must be added to the system boot time stored in epoch format.
* See line 64 of this file to see system boot time stored in epoch algorithm
*/
std::chrono::system_clock::duration tp_dur = (timeP + temp_offset).time_since_epoch();
to_timeval(tp_dur, tp);
} else {
to_timeval(temp_offset, tp);
}

p->setTimestampSeconds((uint32_t) tp.tv_sec);
p->setTimestampMicroseconds((uint32_t) tp.tv_usec);
Expand Down Expand Up @@ -195,18 +201,28 @@ void Packetcapture::packet_in(polycube::service::Direction direction,
const std::vector<uint8_t> &packet) {

Tins::EthernetII pkt(&packet[0], packet.size());
uint64_t t;
ts = false;

switch (direction) {
case polycube::service::Direction::INGRESS:
temp_offset = std::chrono::nanoseconds(static_cast<unsigned long long>(get_array_table<uint64_t>("packet_timestamp", 0, ProgramType::INGRESS).get(0x0)));
t = (((uint64_t) (md.metadata[1]) << 32) | (uint64_t) md.metadata[0]);
if (md.metadata[2] == 0) {
ts = true;
}
temp_offset = std::chrono::nanoseconds(t);
if (getNetworkmode() == true) {
addPacket(packet); /* store the packet in the FIFO queue*/
} else {
writeDump(packet);
}
break;
case polycube::service::Direction::EGRESS:
temp_offset = std::chrono::nanoseconds(static_cast<unsigned long long>(get_array_table<uint64_t>("packet_timestamp", 0, ProgramType::EGRESS).get(0x0)));
t = (((uint64_t) (md.metadata[1]) << 32) | (uint64_t) md.metadata[0]);
if (md.metadata[2] == 0) {
ts = true;
}
temp_offset = std::chrono::nanoseconds(t);
if (getNetworkmode() == true) {
addPacket(packet); /* store the packet in the FIFO queue*/
} else {
Expand Down Expand Up @@ -295,15 +311,17 @@ void Packetcapture::addPacket(const std::vector<uint8_t> &packet) {
PacketJsonObject pj;
auto p = std::shared_ptr<Packet>(new Packet(*this, pj));

/*
* Here the packet capture time offset must be added to the system boot time stored in epoch format.
* See line 58 of this file to see system boot time stored in epoch algorithm
*/

struct timeval tp;
std::chrono::system_clock::duration tp_dur = (timeP + temp_offset).time_since_epoch();
to_timeval(tp_dur, tp);

if (ts) {
/*
* Here the packet capture time offset must be added to the system boot time stored in epoch format.
* See line 64 of this file to see system boot time stored in epoch algorithm
*/
std::chrono::system_clock::duration tp_dur = (timeP + temp_offset).time_since_epoch();
to_timeval(tp_dur, tp);
} else {
to_timeval(temp_offset, tp);
}
p->setTimestampSeconds((uint32_t) tp.tv_sec);
p->setTimestampMicroseconds((uint32_t) tp.tv_usec);
p->setPacketlen((uint32_t) packet.size());
Expand Down Expand Up @@ -378,14 +396,16 @@ void Packetcapture::to_timeval(std::chrono::system_clock::duration& d, struct ti
}

void Packetcapture::setFilter(const std::string &value) {
this->filter = value;
logger()->info("Inserted filter: {0}", filter);
if (filter == "all") {
filterCode = "return pcn_pkt_controller(ctx, md, reason);";
logger()->info("Inserted filter: {0}", value);
if (value == "all") {
filterCode = "if (ctx->tstamp == 0) {\n\tpkt_timestamp = bpf_ktime_get_ns();\n\tmdata[0] = *(&pkt_timestamp);\n\t"
"mdata[1] = (*(&pkt_timestamp)) >> 32;\n\tmdata[2] = 0;\n} else {\n\tmdata[0] = *(&ctx->tstamp);\n\t"
"mdata[1] = (*(&ctx->tstamp)) >> 32;\n\tmdata[2] = 1;\n}\nreturn pcn_pkt_controller_with_metadata(ctx, md, reason, mdata);";
}else {
memset(&cbpf, 0, sizeof(cbpf));
filterCompile(filter, &cbpf);
filterCompile(value, &cbpf);
}
this->filter = value;
updateFilter();
}

Expand All @@ -410,9 +430,8 @@ void Packetcapture::filterCompile(std::string str, struct sock_fprog * cbpf) {

ret = pcap_compile_nopcap(65535, link_type, &_bpf, str.c_str(), 1, 0xffffffff);
if (ret < 0) {
logger()->info("Cannot compile filter: {0}", str);
filterCode = "return RX_OK;";
return;
logger()->error("Cannot compile filter: {0}", str);
throw std::runtime_error("Filter not valid");
}

cbpf->len = _bpf.bf_len;
Expand Down
3 changes: 3 additions & 0 deletions src/services/pcn-packetcapture/src/Packetcapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class Packetcapture : public PacketcaptureBase {
std::chrono::nanoseconds temp_offset;
std::string filter;
bool bootstrap = true; /* variable used to set default filter when the service is created */
bool ts = false; /* true when service not TC type or sk_buff->tstamp == 0 see line 45
* in Packetcapture_dp_egress.c and Packetcapture_dp_ingress.c
*/

private:
struct sock_fprog cbpf;
Expand Down
20 changes: 2 additions & 18 deletions src/services/pcn-packetcapture/src/Packetcapture_dp_egress.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,15 @@
#include <uapi/linux/tcp.h>
#include <uapi/linux/udp.h>

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

/*
* BPF map where a single element, packet timestamp
*/
BPF_ARRAY(packet_timestamp, uint64_t, 1);


static __always_inline int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
unsigned int key = 0;
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct eth_hdr *ethernet = data;
u16 reason = 1;
uint32_t a, x, m[16];

uint64_t *pkt_timestamp = packet_timestamp.lookup(&key);
if (!pkt_timestamp){
return RX_DROP;
}
*pkt_timestamp = bpf_ktime_get_ns();
u32 mdata[3];
uint64_t pkt_timestamp;

//CUSTOM_FILTER_CODE

Expand Down
20 changes: 2 additions & 18 deletions src/services/pcn-packetcapture/src/Packetcapture_dp_ingress.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,15 @@
#include <uapi/linux/tcp.h>
#include <uapi/linux/udp.h>

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

/*
* BPF map where a single element, packet timestamp
*/
BPF_ARRAY(packet_timestamp, uint64_t, 1);


static __always_inline int handle_rx(struct CTXTYPE *ctx, struct pkt_metadata *md) {
unsigned int key = 0;
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct eth_hdr *ethernet = data;
u16 reason = 1;
uint32_t a, x, m[16];

uint64_t *pkt_timestamp = packet_timestamp.lookup(&key);
if (!pkt_timestamp){
return RX_DROP;
}
*pkt_timestamp = bpf_ktime_get_ns();
u32 mdata[3];
uint64_t pkt_timestamp;

//CUSTOM_FILTER_CODE

Expand Down
Loading

0 comments on commit 864b5aa

Please sign in to comment.