[PATCH grout] replace clock_t with Grout specific high-res clock

Morten Brørup mb at smartsharesystems.com
Sun May 24 20:39:34 CEST 2026


> From: Robin Jarry [mailto:rjarry at redhat.com]
> Sent: Sunday, 24 May 2026 16.36
> 
> Hi Morten,
> 
> Morten Brørup, May 24, 2026 at 12:50:
> > 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>
> 
> I have a few remarks:
> 
> 1) Do we really need nanosecond precision? I am not worried about the
>    date limit as 63 bits (signed 64bit integer) allow holding up to 292
>    years. But this seems excessive for a simple timestamp.
> 
>    Or maybe you are planning on adding other less precise types?

Nanosecond resolution opens possibilities, which are not available with microsecond resolution, e.g. shaping and pacing (which I understand is WIP); and the type it replaces also uses 64 bit, so the resolution improvement does not have a memory cost.

Yes, in the long term, I plan to add less precise types.

> 
> 2) Make sure to satisfy `make lint`:
> 
> $ make lint
> [clang-format]
> Clang-formatting 273 files
> modules/infra/control/lacp.c:178:26: error: code should be clang-
> formatted [-Wclang-format-violations]
>                                 member->next_tx = now +
> LACP_SHORT_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
>                                                      ^
> modules/ip/control/icmp.c:49:25: error: code should be clang-formatted
> [-Wclang-format-violations]
> static struct rte_mbuf *get_icmp_response(uint16_t ident, uint16_t
> seq_num, gr_clock_ns_t *timestamp) {
>                         ^
> modules/l2/cli/fdb.c:141:17: error: code should be clang-formatted [-
> Wclang-format-violations]
>                 gr_table_cell(table, 6, "%ld", (gr_clock_ns() - fdb-
> >last_seen) / INT64_C(1000000000));
>                               ^
> modules/l2/cli/fdb.c:141:88: error: code should be clang-formatted [-
> Wclang-format-violations]
>                 gr_table_cell(table, 6, "%ld", (gr_clock_ns() - fdb-
> >last_seen) / INT64_C(1000000000));
> 
> ^
> [license-check]
> [white-space]
> [comments]
> api/gr_clock.h:13:// Note: Using signed, to avoid need for casting to
> signed in calculations where race conditions may cause negative
> differences.<-- comment too long
> api/gr_clock.h:16:// Get powered-on (non-suspended, non-hibernated)
> time since last boot (using a common clock across all processes).<--
> comment too long
> make: *** [GNUmakefile:181: lint] Error 123

I can fix long lines.
What's the max number of characters per line?

How to continue a long line on the next line in Grout?
In DPDK we use double-indentation. E.g.:

int verylongfunction(int a,
		int b);
if (some + very +
		large + sum + continues +
		with + even + more) {
	some_function(some, sum);
	other_function(very, more);
}

Alternatively, we continue at the function brace, using spaces for the continuation indentation, e.g.:

	int verylongfunction(int a,
	                     int b);

Both types of indentation are readable, regardless if the editor is set up to render TAB as 4 or 8 spaces.


"make lint" spews out warnings about things I didn't touch.
Do I need to set up some configuration file or pass special parameters for this to work?

My build server is running: Ubuntu 24.04.<redacted> LTS

$ clang-format --version
Ubuntu clang-format version 18.1.3 (1ubuntu1)

$ make lint
[clang-format]
Clang-formating 273 files
frr/rt_grout.c:529:12: error: code should be clang-formatted [-Wclang-format-violations]
        if (new && nh_id == 0) {
                  ^
frr/rt_grout.c:547:45: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r4_add = (struct gr_ip4_route_add_req) {
                                                                 ^
frr/rt_grout.c:547:48: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r4_add = (struct gr_ip4_route_add_req) {
                                                                    ^
frr/rt_grout.c:548:39: error: code should be clang-formatted [-Wclang-format-violations]
                                .exist_ok = true, .vrf_id = vrf_id
                                                                  ^
frr/rt_grout.c:559:45: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r4_del = (struct gr_ip4_route_del_req) {
                                                                 ^
frr/rt_grout.c:559:48: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r4_del = (struct gr_ip4_route_del_req) {
                                                                    ^
frr/rt_grout.c:560:41: error: code should be clang-formatted [-Wclang-format-violations]
                                .missing_ok = true, .vrf_id = vrf_id
                                                                    ^
frr/rt_grout.c:575:45: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r6_add = (struct gr_ip6_route_add_req) {
                                                                 ^
frr/rt_grout.c:575:48: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r6_add = (struct gr_ip6_route_add_req) {
                                                                    ^
frr/rt_grout.c:576:39: error: code should be clang-formatted [-Wclang-format-violations]
                                .exist_ok = true, .vrf_id = vrf_id
                                                                  ^
frr/rt_grout.c:586:45: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r6_del = (struct gr_ip6_route_del_req) {
                                                                 ^
frr/rt_grout.c:586:48: error: code should be clang-formatted [-Wclang-format-violations]
                        req.r6_del = (struct gr_ip6_route_del_req) {
                                                                    ^
frr/rt_grout.c:587:41: error: code should be clang-formatted [-Wclang-format-violations]
                                .missing_ok = true, .vrf_id = vrf_id
                                                                    ^
frr/rt_grout.c:676:22: error: code should be clang-formatted [-Wclang-format-violations]
                        len += sizeof(*sr6)
                                          ^
frr/rt_grout.c:676:23: error: code should be clang-formatted [-Wclang-format-violations]
                        len += sizeof(*sr6)
                                           ^
modules/dhcp/control/client.c:83:17: error: code should be clang-formatted [-Wclang-format-violations]
                                LOG(WARNING,
                                            ^
modules/dhcp/control/client.c:84:48: error: code should be clang-formatted [-Wclang-format-violations]
                                    "failed to create gateway nexthop: %s",
                                                                           ^
modules/dhcp/control/client.c:85:24: error: code should be clang-formatted [-Wclang-format-violations]
                                    strerror(errno));
                                                   ^
modules/dhcp/control/dhcp.h:122:24: error: code should be clang-formatted [-Wclang-format-violations]
int dhcp_parse_options(
                       ^
modules/dhcp/control/dhcp.h:123:25: error: code should be clang-formatted [-Wclang-format-violations]
        const uint8_t *options,
                               ^
modules/dhcp/control/dhcp.h:124:23: error: code should be clang-formatted [-Wclang-format-violations]
        uint16_t options_len,
                             ^
modules/dhcp/control/dhcp.h:125:23: error: code should be clang-formatted [-Wclang-format-violations]
        struct dhcp_client *,
                             ^
modules/dhcp/control/dhcp.h:126:23: error: code should be clang-formatted [-Wclang-format-violations]
        dhcp_message_type_t *
                             ^
modules/infra/control/ctlplane.c:407:11: error: code should be clang-formatted [-Wclang-format-violations]
                LOG(ERR,
                        ^
modules/infra/control/ctlplane.c:408:45: error: code should be clang-formatted [-Wclang-format-violations]
                    "netlink_link_set_master(%s, %u): %s",
                                                          ^
modules/infra/control/ctlplane.c:409:19: error: code should be clang-formatted [-Wclang-format-violations]
                    iface->name,
                                ^
modules/infra/control/ctlplane.c:410:14: error: code should be clang-formatted [-Wclang-format-violations]
                    master,
                           ^
modules/infra/control/ctlplane.c:411:22: error: code should be clang-formatted [-Wclang-format-violations]
                    strerror(errno));
                                   ^
modules/infra/control/graph.c:636:13: error: code should be clang-formatted [-Wclang-format-violations]
        LOG(NOTICE,
                   ^
modules/infra/control/graph.c:637:38: error: code should be clang-formatted [-Wclang-format-violations]
            "vector_max=%u rx_burst_max=%u",
                                            ^
modules/infra/control/graph.c:638:28: error: code should be clang-formatted [-Wclang-format-violations]
            graph_conf.vector_max,
                                  ^
modules/infra/control/graph.c:639:29: error: code should be clang-formatted [-Wclang-format-violations]
            graph_conf.rx_burst_max);
                                   ^
modules/infra/control/lacp.c:178:26: error: code should be clang-formatted [-Wclang-format-violations]
                                member->next_tx = now + LACP_SHORT_TIMEOUT * (gr_clock_ns_t)NS_PER_S;
                                                     ^
modules/infra/control/port.c:451:16: error: code should be clang-formatted [-Wclang-format-violations]
                        LOG(WARNING,
                                    ^
modules/infra/control/port.c:452:30: error: code should be clang-formatted [-Wclang-format-violations]
                            "rename %s -> %s: %s",
                                                  ^
modules/infra/control/port.c:453:22: error: code should be clang-formatted [-Wclang-format-violations]
                            entry->d_name,
                                          ^
modules/infra/control/port.c:454:17: error: code should be clang-formatted [-Wclang-format-violations]
                            new_name,
                                     ^
modules/infra/control/port.c:455:23: error: code should be clang-formatted [-Wclang-format-violations]
                            strerror(errno));
                                           ^
modules/ip/control/icmp.c:49:25: error: code should be clang-formatted [-Wclang-format-violations]
static struct rte_mbuf *get_icmp_response(uint16_t ident, uint16_t seq_num, gr_clock_ns_t *timestamp) {
                        ^
modules/ip/datapath/ip_input.c:253:20: error: code should be clang-formatted [-Wclang-format-violations]
        gr_conn_parse_key(
                          ^
modules/ip/datapath/ip_input.c:254:24: error: code should be clang-formatted [-Wclang-format-violations]
                const struct iface *,
                                     ^
modules/ip/datapath/ip_input.c:255:23: error: code should be clang-formatted [-Wclang-format-violations]
                const addr_family_t,
                                    ^
modules/ip/datapath/ip_input.c:256:27: error: code should be clang-formatted [-Wclang-format-violations]
                const struct rte_mbuf *,
                                        ^
modules/ip/datapath/ip_input.c:257:20: error: code should be clang-formatted [-Wclang-format-violations]
                struct conn_key *
                                 ^
modules/ip6/datapath/ip6_input.c:257:53: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.src_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                           ^
modules/ip6/datapath/ip6_input.c:257:63: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.src_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                                     ^
modules/ip6/datapath/ip6_input.c:258:65: error: code should be clang-formatted [-Wclang-format-violations]
                0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
                                                                              ^
modules/ip6/datapath/ip6_input.c:270:53: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                           ^
modules/ip6/datapath/ip6_input.c:270:63: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                                     ^
modules/ip6/datapath/ip6_input.c:271:41: error: code should be clang-formatted [-Wclang-format-violations]
                0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
                                                      ^
modules/ip6/datapath/ip6_input.c:284:53: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                           ^
modules/ip6/datapath/ip6_input.c:284:63: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                                     ^
modules/ip6/datapath/ip6_input.c:285:45: error: code should be clang-formatted [-Wclang-format-violations]
                0xff00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
                                                          ^
modules/ip6/datapath/ip6_input.c:291:53: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                           ^
modules/ip6/datapath/ip6_input.c:291:63: error: code should be clang-formatted [-Wclang-format-violations]
        fake_mbuf.ipv6_hdr.dst_addr = (struct rte_ipv6_addr)RTE_IPV6(
                                                                     ^
modules/ip6/datapath/ip6_input.c:292:45: error: code should be clang-formatted [-Wclang-format-violations]
                0xff00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
                                                          ^
modules/ip6/datapath/ip6_output.c:106:32: error: code should be clang-formatted [-Wclang-format-violations]
                        || (l3->flags & GR_NH_F_LINK
                                                    ^
modules/ip6/datapath/ip6_output.c:107:55: error: code should be clang-formatted [-Wclang-format-violations]
                            && !rte_ipv6_addr_eq(&ip->dst_addr, &l3->ipv6)))) {
                                                                           ^
modules/ip6/datapath/ndp_na_input.c:163:49: error: code should be clang-formatted [-Wclang-format-violations]
        ndp_mbuf->na_hdr.target = (struct rte_ipv6_addr)RTE_IPV6(
                                                       ^
modules/ip6/datapath/ndp_na_input.c:163:59: error: code should be clang-formatted [-Wclang-format-violations]
        ndp_mbuf->na_hdr.target = (struct rte_ipv6_addr)RTE_IPV6(
                                                                 ^
modules/ip6/datapath/ndp_na_input.c:164:65: error: code should be clang-formatted [-Wclang-format-violations]
                0xfe80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00aa
                                                                              ^
modules/ip6/datapath/ndp_na_input.c:183:67: error: code should be clang-formatted [-Wclang-format-violations]
        ip6_local_mbuf_data(&ndp_mbuf->mbuf)->dst = (struct rte_ipv6_addr)RTE_IPV6(
                                                                         ^
modules/ip6/datapath/ndp_na_input.c:183:77: error: code should be clang-formatted [-Wclang-format-violations]
        ip6_local_mbuf_data(&ndp_mbuf->mbuf)->dst = (struct rte_ipv6_addr)RTE_IPV6(
                                                                                   ^
modules/ip6/datapath/ndp_na_input.c:184:35: error: code should be clang-formatted [-Wclang-format-violations]
                0xfe80, 0, 0, 0, 0, 0, 0, 0x00bb
                                                ^
modules/ip6/datapath/ndp_na_input.c:239:48: error: code should be clang-formatted [-Wclang-format-violations]
        ndp_mbuf.na_hdr.target = (struct rte_ipv6_addr)RTE_IPV6(
                                                      ^
modules/ip6/datapath/ndp_na_input.c:239:58: error: code should be clang-formatted [-Wclang-format-violations]
        ndp_mbuf.na_hdr.target = (struct rte_ipv6_addr)RTE_IPV6(
                                                                ^
modules/ip6/datapath/ndp_na_input.c:240:45: error: code should be clang-formatted [-Wclang-format-violations]
                0xff02, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
                                                          ^
modules/l2/cli/fdb.c:141:17: error: code should be clang-formatted [-Wclang-format-violations]
                gr_table_cell(table, 6, "%ld", (gr_clock_ns() - fdb->last_seen) / INT64_C(1000000000));
                              ^
modules/l2/cli/fdb.c:141:88: error: code should be clang-formatted [-Wclang-format-violations]
                gr_table_cell(table, 6, "%ld", (gr_clock_ns() - fdb->last_seen) / INT64_C(1000000000));
                                                                                                     ^
modules/policy/control/conntrack.h:50:24: error: code should be clang-formatted [-Wclang-format-violations]
bool gr_conn_parse_key(
                       ^
modules/policy/control/conntrack.h:51:23: error: code should be clang-formatted [-Wclang-format-violations]
        const struct iface *,
                             ^
modules/policy/control/conntrack.h:52:22: error: code should be clang-formatted [-Wclang-format-violations]
        const addr_family_t,
                            ^
modules/policy/control/conntrack.h:53:26: error: code should be clang-formatted [-Wclang-format-violations]
        const struct rte_mbuf *,
                                ^
modules/policy/control/conntrack.h:54:19: error: code should be clang-formatted [-Wclang-format-violations]
        struct conn_key *
                         ^
modules/srv6/control/route.c:67:26: error: code should be clang-formatted [-Wclang-format-violations]
        memcpy(sr6_pub->seglist,
                                ^
modules/srv6/control/route.c:68:27: error: code should be clang-formatted [-Wclang-format-violations]
               sr6_priv->seglist,
                                 ^
modules/srv6/control/route.c:69:57: error: code should be clang-formatted [-Wclang-format-violations]
               sizeof(sr6_pub->seglist[0]) * sr6_pub->n_seglist);
                                                               ^
make: *** [GNUmakefile:175: lint] Error 1


More information about the grout mailing list