back to topotato report
topotato coverage report
Current view: top level - lib - monotime.h (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 20 44 45.5 %
Date: 2023-11-16 17:19:14 Functions: 3 12 25.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: ISC
       2             : /*
       3             :  * Copyright (c) 2017  David Lamparter, for NetDEF, Inc.
       4             :  */
       5             : 
       6             : #ifndef _FRR_MONOTIME_H
       7             : #define _FRR_MONOTIME_H
       8             : 
       9             : #include <stdint.h>
      10             : #include <time.h>
      11             : #include <sys/time.h>
      12             : 
      13             : #ifdef __cplusplus
      14             : extern "C" {
      15             : #endif
      16             : 
      17             : struct fbuf;
      18             : struct printfrr_eargs;
      19             : 
      20             : #ifndef TIMESPEC_TO_TIMEVAL
      21             : /* should be in sys/time.h on BSD & Linux libcs */
      22             : #define TIMESPEC_TO_TIMEVAL(tv, ts)                                            \
      23             :         do {                                                                   \
      24             :                 (tv)->tv_sec = (ts)->tv_sec;                                   \
      25             :                 (tv)->tv_usec = (ts)->tv_nsec / 1000;                          \
      26             :         } while (0)
      27             : #endif
      28             : #ifndef TIMEVAL_TO_TIMESPEC
      29             : /* should be in sys/time.h on BSD & Linux libcs */
      30             : #define TIMEVAL_TO_TIMESPEC(tv, ts)                                            \
      31             :         do {                                                                   \
      32             :                 (ts)->tv_sec = (tv)->tv_sec;                                   \
      33             :                 (ts)->tv_nsec = (tv)->tv_usec * 1000;                          \
      34             :         } while (0)
      35             : #endif
      36             : 
      37             : /* Linux/glibc is sadly missing these timespec helpers */
      38             : #ifndef timespecadd
      39             : #define timespecadd(tsp, usp, vsp)                                             \
      40             :         do {                                                                   \
      41             :                 (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;                 \
      42             :                 (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;              \
      43             :                 if ((vsp)->tv_nsec >= 1000000000L) {                           \
      44             :                         (vsp)->tv_sec++;                                       \
      45             :                         (vsp)->tv_nsec -= 1000000000L;                         \
      46             :                 }                                                              \
      47             :         } while (0)
      48             : #endif
      49             : 
      50             : #ifndef timespecsub
      51             : #define timespecsub(tsp, usp, vsp)                                             \
      52             :         do {                                                                   \
      53             :                 (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;                 \
      54             :                 (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;              \
      55             :                 if ((vsp)->tv_nsec < 0) {                                      \
      56             :                         (vsp)->tv_sec--;                                       \
      57             :                         (vsp)->tv_nsec += 1000000000L;                         \
      58             :                 }                                                              \
      59             :         } while (0)
      60             : #endif
      61             : 
      62       15147 : static inline time_t monotime(struct timeval *tvo)
      63             : {
      64       15147 :         struct timespec ts;
      65             : 
      66       15147 :         clock_gettime(CLOCK_MONOTONIC, &ts);
      67       15134 :         if (tvo) {
      68       15134 :                 TIMESPEC_TO_TIMEVAL(tvo, &ts);
      69             :         }
      70       15130 :         return ts.tv_sec;
      71             : }
      72             : 
      73             : #define ONE_DAY_SECOND (60 * 60 * 24)
      74             : #define ONE_WEEK_SECOND (ONE_DAY_SECOND * 7)
      75             : #define ONE_YEAR_SECOND (ONE_DAY_SECOND * 365)
      76             : 
      77             : /* the following two return microseconds, not time_t!
      78             :  *
      79             :  * also, they're negative forms of each other, but having both makes the
      80             :  * code more readable
      81             :  */
      82          74 : static inline int64_t monotime_since(const struct timeval *ref,
      83             :                                      struct timeval *out)
      84             : {
      85          74 :         struct timeval tv;
      86          74 :         monotime(&tv);
      87          74 :         timersub(&tv, ref, &tv);
      88          74 :         if (out)
      89          17 :                 *out = tv;
      90          74 :         return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
      91             : }
      92             : 
      93        6452 : static inline int64_t monotime_until(const struct timeval *ref,
      94             :                                      struct timeval *out)
      95             : {
      96        6452 :         struct timeval tv;
      97        6452 :         monotime(&tv);
      98        6452 :         timersub(ref, &tv, &tv);
      99        6452 :         if (out)
     100        6446 :                 *out = tv;
     101        6452 :         return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
     102             : }
     103             : 
     104           0 : static inline time_t monotime_to_realtime(const struct timeval *mono,
     105             :                                           struct timeval *realout)
     106             : {
     107           0 :         struct timeval delta, real;
     108             : 
     109           0 :         monotime_since(mono, &delta);
     110           0 :         gettimeofday(&real, NULL);
     111             : 
     112           0 :         timersub(&real, &delta, &real);
     113           0 :         if (realout)
     114           0 :                 *realout = real;
     115           0 :         return real.tv_sec;
     116             : }
     117             : 
     118             : /* Char buffer size for time-to-string api */
     119             : #define MONOTIME_STRLEN 32
     120             : 
     121           0 : static inline char *time_to_string(time_t ts, char *buf)
     122             : {
     123           0 :         struct timeval tv;
     124           0 :         time_t tbuf;
     125             : 
     126           0 :         monotime(&tv);
     127           0 :         tbuf = time(NULL) - (tv.tv_sec - ts);
     128             : 
     129           0 :         return ctime_r(&tbuf, buf);
     130             : }
     131             : 
     132             : /* Convert interval to human-friendly string, used in cli output e.g. */
     133           0 : static inline const char *frrtime_to_interval(time_t t, char *buf,
     134             :                                               size_t buflen)
     135             : {
     136           0 :         struct tm tm;
     137             : 
     138           0 :         gmtime_r(&t, &tm);
     139             : 
     140           0 :         if (t < ONE_DAY_SECOND)
     141           0 :                 snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
     142             :                          tm.tm_sec);
     143           0 :         else if (t < ONE_WEEK_SECOND)
     144           0 :                 snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
     145             :                          tm.tm_min);
     146             :         else
     147           0 :                 snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7,
     148           0 :                          tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
     149           0 :         return buf;
     150             : }
     151             : 
     152             : enum {
     153             :         /* n/a - input was seconds precision, don't print any fractional */
     154             :         TIMEFMT_SECONDS = (1 << 0),
     155             :         /* caller is directly invoking printfrr_time and has pre-specified
     156             :          * I/Iu/Is/M/Mu/Ms/R/Ru/Rs (for printing timers)
     157             :          */
     158             :         TIMEFMT_PRESELECT = (1 << 1),
     159             :         /* don't print any output - this is needed for invoking printfrr_time
     160             :          * from another printfrr extensions to skip over flag characters
     161             :          */
     162             :         TIMEFMT_SKIP = (1 << 2),
     163             :         /* use spaces in appropriate places */
     164             :         TIMEFMT_SPACE = (1 << 3),
     165             : 
     166             :         /* input interpretations: */
     167             :         TIMEFMT_REALTIME = (1 << 8),
     168             :         TIMEFMT_MONOTONIC = (1 << 9),
     169             :         TIMEFMT_SINCE = (1 << 10),
     170             :         TIMEFMT_UNTIL = (1 << 11),
     171             : 
     172             :         TIMEFMT_ABSOLUTE = TIMEFMT_REALTIME | TIMEFMT_MONOTONIC,
     173             :         TIMEFMT_ANCHORS = TIMEFMT_SINCE | TIMEFMT_UNTIL,
     174             : 
     175             :         /* calendaric formats: */
     176             :         TIMEFMT_ISO8601 = (1 << 16),
     177             : 
     178             :         /* interval formats: */
     179             :         /* 't' - use [t]raditional 3-block format */
     180             :         TIMEFMT_BASIC = (1 << 24),
     181             :         /* 'm' - select mm:ss */
     182             :         TIMEFMT_MMSS = (1 << 25),
     183             :         /* 'h' - select hh:mm:ss */
     184             :         TIMEFMT_HHMMSS = (1 << 26),
     185             :         /* 'd' - print as decimal number of seconds */
     186             :         TIMEFMT_DECIMAL = (1 << 27),
     187             :         /* 'mx'/'hx' - replace zero value with "--:--" or "--:--:--" */
     188             :         TIMEFMT_DASHES = (1 << 31),
     189             : 
     190             :         /* helpers for reference */
     191             :         TIMEFMT_TIMER_DEADLINE =
     192             :                 TIMEFMT_PRESELECT | TIMEFMT_MONOTONIC | TIMEFMT_UNTIL,
     193             :         TIMEFMT_TIMER_INTERVAL = TIMEFMT_PRESELECT,
     194             : };
     195             : 
     196             : extern ssize_t printfrr_time(struct fbuf *buf, struct printfrr_eargs *ea,
     197             :                              const struct timespec *ts, unsigned int flags);
     198             : 
     199             : #ifdef __cplusplus
     200             : }
     201             : #endif
     202             : 
     203             : #endif /* _FRR_MONOTIME_H */

Generated by: LCOV version v1.16-topotato