Message ID | 20180806170953.164776-2-ysseung@google.com |
---|---|
State | Changes Requested, archived |
Delegated to: | David Ahern |
Headers | show |
Series | support delivering packets in delayed | expand |
On 8/6/18 11:09 AM, Yousuk Seung wrote: > diff --git a/tc/tc_core.h b/tc/tc_core.h > index 1dfa9a4f773b..a0fe0923d171 100644 > --- a/tc/tc_core.h > +++ b/tc/tc_core.h > @@ -7,6 +7,10 @@ > > #define TIME_UNITS_PER_SEC 1000000 > > +#define NSEC_PER_USEC 1000 > +#define NSEC_PER_MSEC 1000000 > +#define NSEC_PER_SEC 1000000000LL > + These are not specific to tc so a header in include is a better location (utils.h or a new one) > enum link_layer { > LINKLAYER_UNSPEC, > LINKLAYER_ETHERNET, > diff --git a/tc/tc_util.c b/tc/tc_util.c > index d7578528a31b..c39c9046dcae 100644 > --- a/tc/tc_util.c > +++ b/tc/tc_util.c Similarly for these time functions - not specific to tc so move to lib/utils.c > @@ -385,6 +385,61 @@ char *sprint_ticks(__u32 ticks, char *buf) > return sprint_time(tc_core_tick2time(ticks), buf); > } > > +/* 64 bit times are represented internally in nanoseconds */ > +int get_time64(__s64 *time, const char *str) __u64 seems more appropriate than __s64 > +{ > + double nsec; > + char *p; > + > + nsec = strtod(str, &p); > + if (p == str) > + return -1; > + > + if (*p) { > + if (strcasecmp(p, "s") == 0 || > + strcasecmp(p, "sec") == 0 || > + strcasecmp(p, "secs") == 0) > + nsec *= NSEC_PER_SEC; > + else if (strcasecmp(p, "ms") == 0 || > + strcasecmp(p, "msec") == 0 || > + strcasecmp(p, "msecs") == 0) > + nsec *= NSEC_PER_MSEC; > + else if (strcasecmp(p, "us") == 0 || > + strcasecmp(p, "usec") == 0 || > + strcasecmp(p, "usecs") == 0) > + nsec *= NSEC_PER_USEC; > + else if (strcasecmp(p, "ns") == 0 || > + strcasecmp(p, "nsec") == 0 || > + strcasecmp(p, "nsecs") == 0) strncasecmp would be more efficient > + nsec *= 1; > + else > + return -1; > + } > + > + *time = nsec; > + return 0; > +} > + > +void print_time64(char *buf, int len, __s64 time) > +{ > + double nsec = time; > + > + if (time >= NSEC_PER_SEC) > + snprintf(buf, len, "%.3fs", nsec/NSEC_PER_SEC); > + else if (time >= NSEC_PER_MSEC) > + snprintf(buf, len, "%.3fms", nsec/NSEC_PER_MSEC); > + else if (time >= NSEC_PER_USEC) > + snprintf(buf, len, "%.3fus", nsec/NSEC_PER_USEC); > + else > + snprintf(buf, len, "%lldns", time); > +} > + > +char *sprint_time64(__s64 time, char *buf) > +{ > + print_time64(buf, SPRINT_BSIZE-1, time); > + return buf; > +} > + > int get_size(unsigned int *size, const char *str) > { > double sz;
On Sun, Aug 12, 2018 at 3:09 PM David Ahern <dsahern@gmail.com> wrote: > > On 8/6/18 11:09 AM, Yousuk Seung wrote: > > diff --git a/tc/tc_core.h b/tc/tc_core.h > > index 1dfa9a4f773b..a0fe0923d171 100644 > > --- a/tc/tc_core.h > > +++ b/tc/tc_core.h > > @@ -7,6 +7,10 @@ > > > > #define TIME_UNITS_PER_SEC 1000000 > > > > +#define NSEC_PER_USEC 1000 > > +#define NSEC_PER_MSEC 1000000 > > +#define NSEC_PER_SEC 1000000000LL > > + > > These are not specific to tc so a header in include is a better location > (utils.h or a new one) > > > enum link_layer { > > LINKLAYER_UNSPEC, > > LINKLAYER_ETHERNET, > > diff --git a/tc/tc_util.c b/tc/tc_util.c > > index d7578528a31b..c39c9046dcae 100644 > > --- a/tc/tc_util.c > > +++ b/tc/tc_util.c > > Similarly for these time functions - not specific to tc so move to > lib/utils.c > > > @@ -385,6 +385,61 @@ char *sprint_ticks(__u32 ticks, char *buf) > > return sprint_time(tc_core_tick2time(ticks), buf); > > } > > > > +/* 64 bit times are represented internally in nanoseconds */ > > +int get_time64(__s64 *time, const char *str) > > __u64 seems more appropriate than __s64 The reason why these are signed is to leave room in the API to print/manage negative values. Wasting the 64th bit thusly would only matter after extreme uptimes. There was something of a long debate on this when these patches went around the first time. We ended up with signed time in the netem code also. > > +{ > > + double nsec; > > + char *p; > > + > > + nsec = strtod(str, &p); > > + if (p == str) > > + return -1; > > + > > + if (*p) { > > + if (strcasecmp(p, "s") == 0 || > > + strcasecmp(p, "sec") == 0 || > > + strcasecmp(p, "secs") == 0) > > + nsec *= NSEC_PER_SEC; > > + else if (strcasecmp(p, "ms") == 0 || > > + strcasecmp(p, "msec") == 0 || > > + strcasecmp(p, "msecs") == 0) > > + nsec *= NSEC_PER_MSEC; > > + else if (strcasecmp(p, "us") == 0 || > > + strcasecmp(p, "usec") == 0 || > > + strcasecmp(p, "usecs") == 0) > > + nsec *= NSEC_PER_USEC; > > + else if (strcasecmp(p, "ns") == 0 || > > + strcasecmp(p, "nsec") == 0 || > > + strcasecmp(p, "nsecs") == 0) > > strncasecmp would be more efficient > > > + nsec *= 1; > > + else > > + return -1; > > + } > > + > > + *time = nsec; > > + return 0; > > +} > > + > > +void print_time64(char *buf, int len, __s64 time) > > +{ > > + double nsec = time; > > + > > + if (time >= NSEC_PER_SEC) > > + snprintf(buf, len, "%.3fs", nsec/NSEC_PER_SEC); > > + else if (time >= NSEC_PER_MSEC) > > + snprintf(buf, len, "%.3fms", nsec/NSEC_PER_MSEC); > > + else if (time >= NSEC_PER_USEC) > > + snprintf(buf, len, "%.3fus", nsec/NSEC_PER_USEC); > > + else > > + snprintf(buf, len, "%lldns", time); > > +} > > + > > +char *sprint_time64(__s64 time, char *buf) > > +{ > > + print_time64(buf, SPRINT_BSIZE-1, time); > > + return buf; > > +} > > + > > int get_size(unsigned int *size, const char *str) > > { > > double sz;
diff --git a/tc/tc_core.h b/tc/tc_core.h index 1dfa9a4f773b..a0fe0923d171 100644 --- a/tc/tc_core.h +++ b/tc/tc_core.h @@ -7,6 +7,10 @@ #define TIME_UNITS_PER_SEC 1000000 +#define NSEC_PER_USEC 1000 +#define NSEC_PER_MSEC 1000000 +#define NSEC_PER_SEC 1000000000LL + enum link_layer { LINKLAYER_UNSPEC, LINKLAYER_ETHERNET, diff --git a/tc/tc_util.c b/tc/tc_util.c index d7578528a31b..c39c9046dcae 100644 --- a/tc/tc_util.c +++ b/tc/tc_util.c @@ -385,6 +385,61 @@ char *sprint_ticks(__u32 ticks, char *buf) return sprint_time(tc_core_tick2time(ticks), buf); } +/* 64 bit times are represented internally in nanoseconds */ +int get_time64(__s64 *time, const char *str) +{ + double nsec; + char *p; + + nsec = strtod(str, &p); + if (p == str) + return -1; + + if (*p) { + if (strcasecmp(p, "s") == 0 || + strcasecmp(p, "sec") == 0 || + strcasecmp(p, "secs") == 0) + nsec *= NSEC_PER_SEC; + else if (strcasecmp(p, "ms") == 0 || + strcasecmp(p, "msec") == 0 || + strcasecmp(p, "msecs") == 0) + nsec *= NSEC_PER_MSEC; + else if (strcasecmp(p, "us") == 0 || + strcasecmp(p, "usec") == 0 || + strcasecmp(p, "usecs") == 0) + nsec *= NSEC_PER_USEC; + else if (strcasecmp(p, "ns") == 0 || + strcasecmp(p, "nsec") == 0 || + strcasecmp(p, "nsecs") == 0) + nsec *= 1; + else + return -1; + } + + *time = nsec; + return 0; +} + +void print_time64(char *buf, int len, __s64 time) +{ + double nsec = time; + + if (time >= NSEC_PER_SEC) + snprintf(buf, len, "%.3fs", nsec/NSEC_PER_SEC); + else if (time >= NSEC_PER_MSEC) + snprintf(buf, len, "%.3fms", nsec/NSEC_PER_MSEC); + else if (time >= NSEC_PER_USEC) + snprintf(buf, len, "%.3fus", nsec/NSEC_PER_USEC); + else + snprintf(buf, len, "%lldns", time); +} + +char *sprint_time64(__s64 time, char *buf) +{ + print_time64(buf, SPRINT_BSIZE-1, time); + return buf; +} + int get_size(unsigned int *size, const char *str) { double sz; diff --git a/tc/tc_util.h b/tc/tc_util.h index 6632c4f9c528..87be951c622d 100644 --- a/tc/tc_util.h +++ b/tc/tc_util.h @@ -82,12 +82,14 @@ int get_percent_rate64(__u64 *rate, const char *str, const char *dev); int get_size(unsigned int *size, const char *str); int get_size_and_cell(unsigned int *size, int *cell_log, char *str); int get_time(unsigned int *time, const char *str); +int get_time64(__s64 *time, const char *str); int get_linklayer(unsigned int *val, const char *arg); void print_rate(char *buf, int len, __u64 rate); void print_size(char *buf, int len, __u32 size); void print_qdisc_handle(char *buf, int len, __u32 h); void print_time(char *buf, int len, __u32 time); +void print_time64(char *buf, int len, __s64 time); void print_linklayer(char *buf, int len, unsigned int linklayer); void print_devname(enum output_type type, int ifindex); @@ -96,6 +98,7 @@ char *sprint_size(__u32 size, char *buf); char *sprint_qdisc_handle(__u32 h, char *buf); char *sprint_tc_classid(__u32 h, char *buf); char *sprint_time(__u32 time, char *buf); +char *sprint_time64(__s64 time, char *buf); char *sprint_ticks(__u32 ticks, char *buf); char *sprint_linklayer(unsigned int linklayer, char *buf);