Skip to content

Commit

Permalink
introduced helper to retrieve packet timestamp in Unix Epoch (#318)
Browse files Browse the repository at this point in the history
This commit aims to introduce an helper to ease packet's timestamp computation.
Moreover, the new value will refer to the Unix Epoch instead of kernel timer.

Signed-off-by: Simone Magnani <simonemagnani.96@gmail.com>
  • Loading branch information
s41m0n committed Jul 30, 2020
1 parent a5bbab6 commit 5bf5dbf
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Documentation/developers/dataplane.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,31 @@ The VLAN handling in TC and XDP eBPF programs is a little bit different, so poly
- uint8_t **pcn_vlan_pop_tag** (struct CTXTYPE* pkt);
- uint8_t **pcn_vlan_push_tag** (struct CTXTYPE* pkt, u16 eth_proto, u32 vlan_id);

Packet Timestamping
*******************

So far we know that computing packet's timestamp in eBPF is quite tricky, due to the lack of usable kernel helpers.
The only supported function is **bpf_ktime_get_ns()**, which returns the value of a kernel MONOTONIC clock, meaning that
if the device has gone to sleep/suspend that clock is not updated. Moreover, in the **ctx** structure the field **ctx->tstamp**
has not a standard behaviour: we tested that this value can be:

- empty
- Unix epoch timestamp
- Unknown (maybe kernel timer) timestamp

We have introduced an helper function to compute such timestamp referring to Unix Epoch: **pcn_get_packet_epoch(ctx)**.
What basically happens is that to all eBPF program is injected a flag **_EPOCH_BASE** containing a precomputed value. This value
represents the **Unix_Epoch - Kernel_timer** at time X. Calling the helper would increase this value by **bpf_ktime_get_ns()**
nanoseconds, thanks to you obtain the Unix Epoch time of when you call such helper.

In the following release, it will be possible to compute the exact timestamp even though the device sleeps/suspends due to
the introduction of a new **bpf_ktime_get_ns()** function, which in addition will consider the inactivity time (CLOCK_BOOTTIME instead of CLOCK_MONOTONIC).

Known limitations
*****************
- Since you cannot send a packet on multiple ports, multicast, broadcast or any similar functionality has to be implemented in the control path.
- The support for multiple eBPF programs is not yet documented.
- Timestamp will not be exact if the device running Polycube sleeps/suspends during its execution.


Debugging the data plane
Expand Down
29 changes: 29 additions & 0 deletions src/polycubed/src/base_cube.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,32 @@
namespace polycube {
namespace polycubed {

/** Function to compute a base Unix Epoch timestamp to be used as reference by
* all the timestamp computed using pcn_get_packet_epoch(ctx).
*
* Supposing the packet arrives at time X and we precomputed Unix Epoch and
* kernel timer at time Y:
*
* Epoch_at_X = Epoch_at_Y + (Kernel_at_X - Kernel_at_Y)
*
* where Kernel_at_X is given by the function bpf_ktime_get_ns()
* */
uint64_t genBaseTime() {
// getting system clock (to retrieve Unix Epoch)
auto epoch = std::chrono::system_clock::now();
// getting the same time as bpf_ktime_get_ns()
auto up = std::chrono::steady_clock::now();
// return value to be summed to packet's bpf_ktime_get_ns()
return epoch.time_since_epoch().count() - up.time_since_epoch().count();
}

std::vector<std::string> BaseCube::cflags_ = {
std::string("-D_POLYCUBE_MAX_NODES=") +
std::to_string(PatchPanel::_POLYCUBE_MAX_NODES),
std::string("-D_POLYCUBE_MAX_BPF_PROGRAMS=") +
std::to_string(_POLYCUBE_MAX_BPF_PROGRAMS),
std::string("-D_POLYCUBE_MAX_PORTS=") + std::to_string(_POLYCUBE_MAX_PORTS),
std::string("-D_EPOCH_BASE=") + std::to_string(genBaseTime()),
};

BaseCube::BaseCube(const std::string &name, const std::string &service_name,
Expand Down Expand Up @@ -496,6 +516,15 @@ int pcn_vlan_pop_tag(struct CTXTYPE *pkt);
static __always_inline
int pcn_vlan_push_tag(struct CTXTYPE *pkt, u16 eth_proto, u32 vlan_id);
/* helper to get packet timestamp related to Unix Epoch */
static __always_inline
uint64_t pcn_get_packet_tstamp(struct CTXTYPE *ctx) {
/* Too much variadic, do not know a priori what timestamp is
if(ctx->tstamp != 0) {
return bpf_ntohl(ctx->tstamp);
}*/
return _EPOCH_BASE + bpf_ktime_get_ns();
}
)";

} // namespace polycubed
Expand Down

0 comments on commit 5bf5dbf

Please sign in to comment.