[PATCH grout] replace clock_t with Grout specific high-res clock
Morten Brørup
mb at smartsharesystems.com
Sun May 24 12:50:35 CEST 2026
The clock_t type is implementation specific.
E.g. on Linux, it is microseconds, and on Windows it is milliseconds.
Replace all uses of clock_t and its accompanying function, gr_clock_us(),
with a new nanosecond resolution clock type, gr_clock_ns_t, and its
accompanying function, gr_grout_ns().
Note about signedness:
I condidered making the gr_clock_ns_t unsigned, but that would require
additional considerations in code where it is used, e.g. for calculating
age, to prevent wraparound in race conditions. E.g.:
age = (gr_clock_ns() - fdb->last_seen) / NS_PER_S;
If the current thread reads the clock using gr_clock_ns(), and another
thread races to set fdb->last_seen afterwards, the result of the
subtraction is negative. The division by NS_PER_S makes the age zero.
If gr_clock_ns_t was unsigned, the negative result of the subtraction
would be a very large unsigned number. Dividing this very large number
by NS_PER_S would be a large unsigned number, not zero.
Obviously, this could be fixed by type casting gr_clock_ns_t values to
signed int64_t everywhere they are used with subtraction. But such a
requirement increases the risk of bugs.
So I decided to make it signed, like type_t.
Signed-off-by: Morten Brørup <mb at smartsharesystems.com>
---
api/gr_clock.h | 17 +++++++++++++----
cli/main.c | 2 +-
modules/infra/control/bond.h | 5 +++--
modules/infra/control/l3_nexthop.c | 4 ++--
modules/infra/control/lacp.c | 14 +++++++-------
modules/infra/control/nexthop.h | 4 ++--
modules/ip/api/gr_ip4.h | 2 +-
modules/ip/control/icmp.c | 6 +++---
modules/ip/control/nexthop.c | 2 +-
modules/ip/datapath/arp_output_request.c | 2 +-
modules/ip/datapath/icmp_input.c | 2 +-
modules/ip/datapath/icmp_local_send.c | 10 +++++-----
modules/ip6/api/gr_ip6.h | 2 +-
modules/ip6/control/icmp6.c | 10 +++++-----
modules/ip6/control/nexthop.c | 2 +-
modules/ip6/datapath/icmp6_input.c | 2 +-
modules/ip6/datapath/icmp6_local_send.c | 6 +++---
modules/ip6/datapath/ndp_ns_output.c | 2 +-
modules/l2/api/gr_l2.h | 3 ++-
modules/l2/cli/fdb.c | 2 +-
modules/l2/control/fdb.c | 12 ++++++------
modules/policy/api/gr_conntrack.h | 2 +-
modules/policy/cli/conntrack.c | 6 +++---
modules/policy/control/conntrack.c | 6 +++---
modules/policy/control/conntrack.h | 2 +-
smoke/fib_inject.c | 6 +++---
26 files changed, 72 insertions(+), 61 deletions(-)
diff --git a/api/gr_clock.h b/api/gr_clock.h
index 07741b6a..a0d8f56f 100644
--- a/api/gr_clock.h
+++ b/api/gr_clock.h
@@ -1,20 +1,29 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2025 Robin Jarry
+// Copyright (c) 2026 SmartShare Systems
#pragma once
#include <stdint.h>
#include <time.h>
-// Get the elapsed time since last boot (using a common clock across all processes).
+// High-resolution clock [nanoseconds].
+// Used with CLOCK_MONOTONIC_RAW, unless otherwise specified.
+// Note: Does not have Y2038 problems. Not even with CLOCK_REALTIME.
+// Note: Using signed, to avoid need for casting to signed in calculations where race conditions may cause negative differences.
+typedef int64_t gr_clock_ns_t;
+
+// Get powered-on (non-suspended, non-hibernated) time since last boot (using a common clock across all processes).
static inline struct timespec gr_clock_raw(void) {
struct timespec tp = {0};
clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
return tp;
}
-// Get elapsed time since last boot in microseconds.
-static inline clock_t gr_clock_us(void) {
+// Get powered-on (non-suspended, non-hibernated) time since last boot in nanoseconds.
+// Does not return negative values.
+static inline gr_clock_ns_t gr_clock_ns(void) {
struct timespec tp = gr_clock_raw();
- return (tp.tv_sec * CLOCKS_PER_SEC) + (tp.tv_nsec / 1000);
+ uint64_t ret = (uint64_t)tp.tv_sec * UINT64_C(1000000000) + (uint64_t)tp.tv_nsec;
+ return (int64_t)ret;
}
diff --git a/cli/main.c b/cli/main.c
index 17b822c6..defaedcf 100644
--- a/cli/main.c
+++ b/cli/main.c
@@ -179,7 +179,7 @@ int main(int argc, char **argv) {
tty_init();
// initialize a non-constant seed for random() calls
- srandom(gr_clock_us());
+ srandom(gr_clock_ns());
if (ec_init() < 0) {
errorf("ec_init: %s", strerror(errno));
diff --git a/modules/infra/control/bond.h b/modules/infra/control/bond.h
index 371c5bad..ad7d4dd6 100644
--- a/modules/infra/control/bond.h
+++ b/modules/infra/control/bond.h
@@ -6,6 +6,7 @@
#include "iface.h"
#include "lacp.h"
+#include <gr_clock.h>
#include <gr_infra.h>
#include <stdint.h>
@@ -16,8 +17,8 @@ struct bond_member {
struct iface *iface;
bool active;
bool need_to_transmit; // Need to send immediately
- clock_t next_tx; // Next time we need to send a LACP packet
- clock_t last_rx; // Last time we received a LACP packet
+ gr_clock_ns_t next_tx; // Next time we need to send a LACP packet
+ gr_clock_ns_t last_rx; // Last time we received a LACP packet
// For direct inclusion in LACP packets
struct lacp_participant local;
struct lacp_participant remote;
diff --git a/modules/infra/control/l3_nexthop.c b/modules/infra/control/l3_nexthop.c
index 90076ea3..92ca484b 100644
--- a/modules/infra/control/l3_nexthop.c
+++ b/modules/infra/control/l3_nexthop.c
@@ -295,12 +295,12 @@ static struct nexthop_type_ops l3_nh_ops = {
static void l3_age(struct nexthop *nh, struct nexthop_info_l3 *l3) {
const struct nexthop_af_ops *ops;
- clock_t now = gr_clock_us();
+ gr_clock_ns_t now = gr_clock_ns();
unsigned probes, max_probes;
time_t reply_age;
ops = af_ops[l3->af];
- reply_age = (now - l3->last_reply) / CLOCKS_PER_SEC;
+ reply_age = (now - l3->last_reply) / NS_PER_S;
max_probes = nh_conf.max_ucast_probes + nh_conf.max_bcast_probes;
probes = l3->ucast_probes + l3->bcast_probes;
diff --git a/modules/infra/control/lacp.c b/modules/infra/control/lacp.c
index 63fb101b..cf3b693e 100644
--- a/modules/infra/control/lacp.c
+++ b/modules/infra/control/lacp.c
@@ -65,7 +65,7 @@ void lacp_input_cb(void *obj, uintptr_t, const struct control_queue_drain *drain
// Store partner information from received PDU
member->remote = pdu->actor;
- member->last_rx = gr_clock_us();
+ member->last_rx = gr_clock_ns();
// Save old member state to detect changes
bool old_active = member->active;
@@ -119,10 +119,10 @@ static void lacp_periodic(evutil_socket_t, short, void *) {
struct iface_info_bond *bond;
struct bond_member *member;
const struct iface *port;
- clock_t now, timeout;
+ gr_clock_ns_t now, timeout;
struct iface *iface;
- now = gr_clock_us();
+ now = gr_clock_ns();
iface = NULL;
while ((iface = iface_next(GR_IFACE_TYPE_BOND, iface)) != NULL) {
@@ -139,9 +139,9 @@ static void lacp_periodic(evutil_socket_t, short, void *) {
// Check for timeout if we've received at least one PDU
if (member->last_rx != 0) {
if (member->local.state & LACP_STATE_FAST)
- timeout = LACP_SHORT_TIMEOUT * US_PER_S;
+ timeout = LACP_SHORT_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
else
- timeout = LACP_LONG_TIMEOUT * US_PER_S;
+ timeout = LACP_LONG_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
if (now - member->last_rx > timeout && member->active) {
// Partner timed out - enter FAILED state
@@ -175,9 +175,9 @@ static void lacp_periodic(evutil_socket_t, short, void *) {
member->need_to_transmit = false;
if (member->remote.state & LACP_STATE_FAST)
- member->next_tx = now + LACP_SHORT_TIMEOUT * US_PER_S;
+ member->next_tx = now + LACP_SHORT_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
else
- member->next_tx = now + LACP_LONG_TIMEOUT * US_PER_S;
+ member->next_tx = now + LACP_LONG_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
}
// Update active members list if any port timed out
diff --git a/modules/infra/control/nexthop.h b/modules/infra/control/nexthop.h
index 934796bf..5cf72a3a 100644
--- a/modules/infra/control/nexthop.h
+++ b/modules/infra/control/nexthop.h
@@ -41,8 +41,8 @@ static_assert(sizeof(struct nexthop) <= (RTE_CACHE_LINE_MIN_SIZE * 2));
GR_NH_TYPE_INFO(GR_NH_T_L3, nexthop_info_l3, {
BASE(gr_nexthop_info_l3);
- clock_t last_reply; //!< timestamp when last update was received
- clock_t last_request;
+ gr_clock_ns_t last_reply; //!< timestamp when last update was received
+ gr_clock_ns_t last_request;
uint8_t ucast_probes;
uint8_t bcast_probes;
diff --git a/modules/ip/api/gr_ip4.h b/modules/ip/api/gr_ip4.h
index c150863e..8bf13a4b 100644
--- a/modules/ip/api/gr_ip4.h
+++ b/modules/ip/api/gr_ip4.h
@@ -143,7 +143,7 @@ struct gr_ip4_icmp_recv_resp {
uint16_t ident;
uint16_t seq_num;
ip4_addr_t src_addr;
- clock_t response_time;
+ gr_clock_ns_t response_time;
};
GR_REQ(GR_IP4_ICMP_RECV, struct gr_ip4_icmp_recv_req, struct gr_ip4_icmp_recv_resp);
diff --git a/modules/ip/control/icmp.c b/modules/ip/control/icmp.c
index c07712e5..9e836c5b 100644
--- a/modules/ip/control/icmp.c
+++ b/modules/ip/control/icmp.c
@@ -15,7 +15,7 @@
struct icmp_queue_item {
struct rte_mbuf *mbuf;
- clock_t timestamp;
+ gr_clock_ns_t timestamp;
STAILQ_ENTRY(icmp_queue_item) next;
};
@@ -46,7 +46,7 @@ static void icmp_input_cb(void *m, uintptr_t timestamp, const struct control_que
// Search for the oldest ICMP response matching the given identifier.
// If found, the packet is removed from the queue.
-static struct rte_mbuf *get_icmp_response(uint16_t ident, uint16_t seq_num, clock_t *timestamp) {
+static struct rte_mbuf *get_icmp_response(uint16_t ident, uint16_t seq_num, gr_clock_ns_t *timestamp) {
struct icmp_queue_item *i, *tmp;
struct rte_mbuf *mbuf = NULL;
@@ -105,7 +105,7 @@ out:
static struct api_out icmp_recv(const void *request, struct api_ctx *) {
const struct gr_ip4_icmp_recv_req *icmp_req = request;
struct gr_ip4_icmp_recv_resp *resp = NULL;
- clock_t *pkt_timestamp, rcv_timestamp;
+ gr_clock_ns_t *pkt_timestamp, rcv_timestamp;
struct rte_icmp_hdr *icmp;
struct rte_ipv4_hdr *ip;
struct rte_mbuf *m;
diff --git a/modules/ip/control/nexthop.c b/modules/ip/control/nexthop.c
index c9006146..3ef0c3e9 100644
--- a/modules/ip/control/nexthop.c
+++ b/modules/ip/control/nexthop.c
@@ -187,7 +187,7 @@ void arp_probe_input_cb(void *obj, uintptr_t, const struct control_queue_drain *
// static next hops never need updating
if (!(l3->flags & GR_NH_F_STATIC)) {
// Refresh all fields.
- l3->last_reply = gr_clock_us();
+ l3->last_reply = gr_clock_ns();
l3->state = GR_NH_S_REACHABLE;
l3->ucast_probes = 0;
l3->bcast_probes = 0;
diff --git a/modules/ip/datapath/arp_output_request.c b/modules/ip/datapath/arp_output_request.c
index 67db9df0..9633cdcf 100644
--- a/modules/ip/datapath/arp_output_request.c
+++ b/modules/ip/datapath/arp_output_request.c
@@ -35,7 +35,7 @@ int arp_output_request_solicit(struct nexthop *nh) {
} else {
// This function is called by the control plane main thread.
// It is OK to modify the nexthop here.
- l3->last_request = gr_clock_us();
+ l3->last_request = gr_clock_ns();
if (l3->ucast_probes < nh_conf.max_ucast_probes)
l3->ucast_probes++;
else
diff --git a/modules/ip/datapath/icmp_input.c b/modules/ip/datapath/icmp_input.c
index 167cc9d7..b0426246 100644
--- a/modules/ip/datapath/icmp_input.c
+++ b/modules/ip/datapath/icmp_input.c
@@ -55,7 +55,7 @@ icmp_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
ip_data->src = ip;
edge = OUTPUT;
} else if (icmp_cb[icmp->icmp_type]) {
- control_output_set_cb(mbuf, icmp_cb[icmp->icmp_type], gr_clock_us());
+ control_output_set_cb(mbuf, icmp_cb[icmp->icmp_type], gr_clock_ns());
edge = CONTROL;
} else {
edge = UNSUPPORTED;
diff --git a/modules/ip/datapath/icmp_local_send.c b/modules/ip/datapath/icmp_local_send.c
index cc504e5c..3377b3a8 100644
--- a/modules/ip/datapath/icmp_local_send.c
+++ b/modules/ip/datapath/icmp_local_send.c
@@ -90,18 +90,18 @@ static uint16_t icmp_local_send_process(
struct rte_icmp_hdr *icmp;
struct ctl_to_stack *msg;
struct rte_mbuf *mbuf;
- clock_t *payload;
+ gr_clock_ns_t *payload;
rte_edge_t next;
for (unsigned i = 0; i < n_objs; i++) {
mbuf = objs[i];
msg = control_input_mbuf_data(mbuf)->data;
icmp = (struct rte_icmp_hdr *)rte_pktmbuf_append(
- mbuf, sizeof(*icmp) + sizeof(clock_t)
+ mbuf, sizeof(*icmp) + sizeof(gr_clock_ns_t)
);
- payload = rte_pktmbuf_mtod_offset(mbuf, clock_t *, sizeof(*icmp));
- *payload = gr_clock_us();
+ payload = rte_pktmbuf_mtod_offset(mbuf, gr_clock_ns_t *, sizeof(*icmp));
+ *payload = gr_clock_ns();
// Build ICMP packet
icmp->icmp_type = RTE_ICMP_TYPE_ECHO_REQUEST;
@@ -116,7 +116,7 @@ static uint16_t icmp_local_send_process(
data = ip_local_mbuf_data(mbuf);
data->proto = IPPROTO_ICMP;
- data->len = sizeof(*icmp) + sizeof(clock_t);
+ data->len = sizeof(*icmp) + sizeof(gr_clock_ns_t);
data->dst = msg->dst;
data->src = msg->src;
data->vrf_id = msg->vrf_id;
diff --git a/modules/ip6/api/gr_ip6.h b/modules/ip6/api/gr_ip6.h
index bb147a43..d060b191 100644
--- a/modules/ip6/api/gr_ip6.h
+++ b/modules/ip6/api/gr_ip6.h
@@ -208,7 +208,7 @@ struct gr_ip6_icmp_recv_resp {
uint16_t ident;
uint16_t seq_num;
struct rte_ipv6_addr src_addr;
- clock_t response_time;
+ gr_clock_ns_t response_time;
};
GR_REQ(GR_IP6_ICMP6_RECV, struct gr_ip6_icmp_recv_req, struct gr_ip6_icmp_recv_resp);
diff --git a/modules/ip6/control/icmp6.c b/modules/ip6/control/icmp6.c
index d0ae86dc..2a3098eb 100644
--- a/modules/ip6/control/icmp6.c
+++ b/modules/ip6/control/icmp6.c
@@ -15,7 +15,7 @@
struct icmp_queue_item {
struct rte_mbuf *mbuf;
- clock_t timestamp;
+ gr_clock_ns_t timestamp;
STAILQ_ENTRY(icmp_queue_item) next;
};
@@ -44,13 +44,13 @@ static void icmp6_input_cb(void *m, uintptr_t timestamp, const struct control_qu
}
#define ICMP6_ERROR_PKT_LEN \
- (GR_ICMP6_HDR_LEN + sizeof(struct rte_ipv6_hdr) + GR_ICMP6_HDR_LEN + sizeof(clock_t))
+ (GR_ICMP6_HDR_LEN + sizeof(struct rte_ipv6_hdr) + GR_ICMP6_HDR_LEN + sizeof(gr_clock_ns_t))
static struct rte_mbuf *get_icmp6_echo_reply(
uint16_t ident,
uint16_t seq_num,
struct icmp6 **out_icmp6,
- clock_t *timestamp
+ gr_clock_ns_t *timestamp
) {
struct icmp_queue_item *i, *tmp;
struct rte_mbuf *mbuf;
@@ -61,7 +61,7 @@ static struct rte_mbuf *get_icmp6_echo_reply(
STAILQ_FOREACH_SAFE (i, &icmp_queue, next, tmp) {
mbuf = i->mbuf;
- if (rte_pktmbuf_pkt_len(mbuf) < GR_ICMP6_HDR_LEN + sizeof(clock_t))
+ if (rte_pktmbuf_pkt_len(mbuf) < GR_ICMP6_HDR_LEN + sizeof(gr_clock_ns_t))
goto free_and_skip;
icmp6 = rte_pktmbuf_mtod(mbuf, struct icmp6 *);
@@ -112,7 +112,7 @@ static struct api_out icmp6_recv(const void *request, struct api_ctx *) {
struct ip6_local_mbuf_data *d_ip6;
struct icmp6 *icmp6;
struct icmp6_echo_reply *icmp6_echo;
- clock_t *pkt_timestamp, rcv_timestamp;
+ gr_clock_ns_t *pkt_timestamp, rcv_timestamp;
struct rte_mbuf *m;
int ret = 0;
diff --git a/modules/ip6/control/nexthop.c b/modules/ip6/control/nexthop.c
index 2012bda1..5e53cc52 100644
--- a/modules/ip6/control/nexthop.c
+++ b/modules/ip6/control/nexthop.c
@@ -236,7 +236,7 @@ void ndp_probe_input_cb(void *obj, uintptr_t, const struct control_queue_drain *
if (!(l3->flags & GR_NH_F_STATIC) && lladdr_found == ICMP6_OPT_FOUND) {
// Refresh all fields.
- l3->last_reply = gr_clock_us();
+ l3->last_reply = gr_clock_ns();
l3->state = GR_NH_S_REACHABLE;
l3->ucast_probes = 0;
l3->bcast_probes = 0;
diff --git a/modules/ip6/datapath/icmp6_input.c b/modules/ip6/datapath/icmp6_input.c
index 6ce747d0..cbeb3f7e 100644
--- a/modules/ip6/datapath/icmp6_input.c
+++ b/modules/ip6/datapath/icmp6_input.c
@@ -82,7 +82,7 @@ icmp6_input_process(struct rte_graph *graph, struct rte_node *node, void **objs,
case ICMP6_TYPE_ROUTER_ADVERT:
default:
if (icmp6_cb[icmp6->type] != NULL) {
- control_output_set_cb(mbuf, icmp6_cb[icmp6->type], gr_clock_us());
+ control_output_set_cb(mbuf, icmp6_cb[icmp6->type], gr_clock_ns());
next = CONTROL;
} else {
next = UNSUPPORTED;
diff --git a/modules/ip6/datapath/icmp6_local_send.c b/modules/ip6/datapath/icmp6_local_send.c
index 676935c2..4da94801 100644
--- a/modules/ip6/datapath/icmp6_local_send.c
+++ b/modules/ip6/datapath/icmp6_local_send.c
@@ -85,14 +85,14 @@ static uint16_t icmp6_local_send_process(
struct ctl_to_stack *msg;
struct rte_mbuf *mbuf;
struct icmp6 *icmp6;
- clock_t *payload;
+ gr_clock_ns_t *payload;
rte_edge_t next;
size_t pkt_len;
for (unsigned i = 0; i < n_objs; i++) {
mbuf = objs[i];
msg = control_input_mbuf_data(mbuf)->data;
- pkt_len = sizeof(*icmp6) + sizeof(*icmp6_echo) + sizeof(clock_t);
+ pkt_len = sizeof(*icmp6) + sizeof(*icmp6_echo) + sizeof(gr_clock_ns_t);
icmp6 = (struct icmp6 *)rte_pktmbuf_append(mbuf, pkt_len);
icmp6->type = ICMP6_TYPE_ECHO_REQUEST;
@@ -108,7 +108,7 @@ static uint16_t icmp6_local_send_process(
mbuf->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
payload = PAYLOAD(icmp6_echo);
- *payload = gr_clock_us();
+ *payload = gr_clock_ns();
data = ip6_local_mbuf_data(mbuf);
data->iface = iface_from_id(msg->iface_id);
diff --git a/modules/ip6/datapath/ndp_ns_output.c b/modules/ip6/datapath/ndp_ns_output.c
index 22f9da34..7c059392 100644
--- a/modules/ip6/datapath/ndp_ns_output.c
+++ b/modules/ip6/datapath/ndp_ns_output.c
@@ -32,7 +32,7 @@ int nh6_solicit(struct nexthop *nh) {
// This function is called by the control plane main thread.
// It is OK to modify the nexthop here.
- l3->last_request = gr_clock_us();
+ l3->last_request = gr_clock_ns();
if (l3->ucast_probes < nh_conf.max_ucast_probes)
l3->ucast_probes++;
else
diff --git a/modules/l2/api/gr_l2.h b/modules/l2/api/gr_l2.h
index b1088a4e..071ec409 100644
--- a/modules/l2/api/gr_l2.h
+++ b/modules/l2/api/gr_l2.h
@@ -5,6 +5,7 @@
#include <gr_api.h>
#include <gr_bitops.h>
+#include <gr_clock.h>
#include <gr_macro.h>
#include <gr_net_types.h>
@@ -74,7 +75,7 @@ struct gr_fdb_entry {
uint16_t iface_id; // Updated automatically when a MAC moves between members.
struct l3_addr vtep; // Remote VTEP for VXLAN-learned entries, 0 for local.
gr_fdb_flags_t flags;
- clock_t last_seen; // Refreshed on each datapath hit for learned entries.
+ gr_clock_ns_t last_seen; // Refreshed on each datapath hit for learned entries.
};
enum gr_l2_requests : uint32_t {
diff --git a/modules/l2/cli/fdb.c b/modules/l2/cli/fdb.c
index 532e5045..94439741 100644
--- a/modules/l2/cli/fdb.c
+++ b/modules/l2/cli/fdb.c
@@ -138,7 +138,7 @@ static cmd_status_t fdb_show(struct gr_api_client *c, const struct ec_pnode *p)
if (fdb_format_flags(flags, sizeof(flags), fdb->flags))
gr_table_cell(table, 5, "%s", flags);
- gr_table_cell(table, 6, "%ld", (gr_clock_us() - fdb->last_seen) / CLOCKS_PER_SEC);
+ gr_table_cell(table, 6, "%ld", (gr_clock_ns() - fdb->last_seen) / INT64_C(1000000000));
if (gr_table_print_row(table) < 0)
break;
diff --git a/modules/l2/control/fdb.c b/modules/l2/control/fdb.c
index 3982cce1..0c8b87b6 100644
--- a/modules/l2/control/fdb.c
+++ b/modules/l2/control/fdb.c
@@ -138,7 +138,7 @@ void fdb_learn(
fdb = data;
}
- fdb->last_seen = gr_clock_us();
+ fdb->last_seen = gr_clock_ns();
if ((fdb->flags & GR_FDB_F_LEARN)
&& (fdb->iface_id != iface_id || !l3_addr_eq(&fdb->vtep, vtep))) {
@@ -207,7 +207,7 @@ static struct api_out fdb_add(const void *request, struct api_ctx *) {
e = data;
*e = req->fdb;
e->bridge_id = iface->id;
- e->last_seen = gr_clock_us();
+ e->last_seen = gr_clock_ns();
if ((ret = rte_hash_add_key_data(fdb_hash, &key, data)) < 0) {
rte_mempool_put(fdb_pool, e);
@@ -219,7 +219,7 @@ static struct api_out fdb_add(const void *request, struct api_ctx *) {
e = data;
*e = req->fdb;
e->bridge_id = iface->id;
- e->last_seen = gr_clock_us();
+ e->last_seen = gr_clock_ns();
event_push(GR_EVENT_FDB_UPDATE, e);
} else {
@@ -400,11 +400,11 @@ static void fdb_ageing_cb(evutil_socket_t, short /*what*/, void * /*priv*/) {
uint32_t next = 0;
uint16_t max_age;
const void *key;
- clock_t now;
+ gr_clock_ns_t now;
void *data;
time_t age;
- now = gr_clock_us();
+ now = gr_clock_ns();
while (rte_hash_iterate(fdb_hash, &key, &data, &next) >= 0) {
fdb = data;
@@ -412,7 +412,7 @@ static void fdb_ageing_cb(evutil_socket_t, short /*what*/, void * /*priv*/) {
if ((fdb->flags & GR_FDB_F_STATIC) || !(fdb->flags & GR_FDB_F_LEARN))
continue;
- age = (now - fdb->last_seen) / CLOCKS_PER_SEC;
+ age = (now - fdb->last_seen) / NS_PER_S;
bridge = iface_from_id(fdb->bridge_id);
if (bridge != NULL)
diff --git a/modules/policy/api/gr_conntrack.h b/modules/policy/api/gr_conntrack.h
index de9722b3..5d6bd75b 100644
--- a/modules/policy/api/gr_conntrack.h
+++ b/modules/policy/api/gr_conntrack.h
@@ -70,7 +70,7 @@ struct gr_conntrack {
uint8_t proto;
struct gr_conntrack_flow fwd_flow;
struct gr_conntrack_flow rev_flow;
- clock_t last_update;
+ gr_clock_ns_t last_update;
uint32_t id;
gr_conn_state_t state;
};
diff --git a/modules/policy/cli/conntrack.c b/modules/policy/cli/conntrack.c
index 7eb38121..6b717fc8 100644
--- a/modules/policy/cli/conntrack.c
+++ b/modules/policy/cli/conntrack.c
@@ -16,7 +16,7 @@
static cmd_status_t conn_list(struct gr_api_client *c, const struct ec_pnode *) {
const struct gr_conntrack *conn;
- clock_t now;
+ gr_clock_ns_t now;
int ret;
struct gr_table *table = gr_table_new();
@@ -31,7 +31,7 @@ static cmd_status_t conn_list(struct gr_api_client *c, const struct ec_pnode *)
gr_table_column(table, "DPORT", GR_DISP_RIGHT | GR_DISP_INT); // 8
gr_table_column(table, "LAST_UPDATE", GR_DISP_RIGHT); // 9
- now = gr_clock_us();
+ now = gr_clock_ns();
gr_api_client_stream_foreach (conn, ret, c, GR_CONNTRACK_LIST, 0, NULL) {
gr_table_cell(table, 0, "%s", iface_name_from_id(c, conn->iface_id));
@@ -55,7 +55,7 @@ static cmd_status_t conn_list(struct gr_api_client *c, const struct ec_pnode *)
gr_table_cell(table, 7, "%u", ntohs(conn->fwd_flow.src_id));
gr_table_cell(table, 8, "%u", ntohs(conn->fwd_flow.dst_id));
- gr_table_cell(table, 9, "%lu", (now - conn->last_update) / 1000000);
+ gr_table_cell(table, 9, "%ld", (now - conn->last_update) / NS_PER_S);
if (gr_table_print_row(table) < 0)
break;
diff --git a/modules/policy/control/conntrack.c b/modules/policy/control/conntrack.c
index 713bc554..fcbf04fe 100644
--- a/modules/policy/control/conntrack.c
+++ b/modules/policy/control/conntrack.c
@@ -240,7 +240,7 @@ again:
goto again;
}
- atomic_store(&c->last_update, gr_clock_us());
+ atomic_store(&c->last_update, gr_clock_ns());
}
bool gr_conn_parse_key(
@@ -389,7 +389,7 @@ struct conn *gr_conn_insert(const struct conn_key *fwd_key, const struct conn_ke
}
static void do_ageing(evutil_socket_t, short /*what*/, void * /*priv*/) {
- clock_t now = gr_clock_us(), last;
+ gr_clock_ns_t now = gr_clock_ns(), last;
uint64_t age, timeout;
struct conn *conn;
const void *key;
@@ -444,7 +444,7 @@ static void do_ageing(evutil_socket_t, short /*what*/, void * /*priv*/) {
last = atomic_load(&conn->last_update);
if (last > now)
continue;
- age = (now - last) / 1000000ULL;
+ age = (now - last) / NS_PER_S;
if (age > timeout)
gr_conn_destroy(conn);
}
diff --git a/modules/policy/control/conntrack.h b/modules/policy/control/conntrack.h
index bb3ea1e5..51f8dd7c 100644
--- a/modules/policy/control/conntrack.h
+++ b/modules/policy/control/conntrack.h
@@ -43,7 +43,7 @@ struct conn {
struct conn_key fwd_key;
struct conn_key rev_key;
_Atomic(gr_conn_state_t) state;
- _Atomic(clock_t) last_update;
+ _Atomic(gr_clock_ns_t) last_update;
struct nat44 nat;
};
diff --git a/smoke/fib_inject.c b/smoke/fib_inject.c
index fee50c32..bf7b96ab 100644
--- a/smoke/fib_inject.c
+++ b/smoke/fib_inject.c
@@ -194,7 +194,7 @@ int main(int argc, char **argv) {
unsigned dist_count;
bool ipv6 = false;
float duration;
- clock_t time;
+ gr_clock_ns_t time;
int ret;
int o;
@@ -242,14 +242,14 @@ int main(int argc, char **argv) {
if (create_nexthops(c) < 0)
return EXIT_FAILURE;
- time = gr_clock_us();
+ time = gr_clock_ns();
if (ipv6)
ret = inject_ipv6(c, count);
else
ret = inject_ipv4(c, count);
- duration = (float)(gr_clock_us() - time) / (float)CLOCKS_PER_SEC;
+ duration = (float)(gr_clock_ns() - time) / (float)1000000000;
printf("total time: %.1fs (%.1f routes/s)\n", duration, (float)count / duration);
--
2.43.0
More information about the grout
mailing list