Commit 292264de authored by David S. Miller's avatar David S. Miller

Merge branch 'net-timestamps-y2038'

Deepa Dinamani says:

====================
Convert network timestamps to be y2038 safe

Introduction:

The series is aimed at transitioning network timestamps to being
y2038 safe.
All patches can be reviewed and merged independently.

Socket timestamps and ioctl calls will be handled separately.

Thanks to Arnd Bergmann for discussing solution options with me.

Solution:

Data type struct timespec is not y2038 safe.
Replace timespec with struct timespec64 which is y2038 safe.

Changes v1 -> v2:
  Move and rename inet_current_time() as discussed
  Squash patches 1 and 2
  Reword commit text for patch 2/3
  Carry over review tags
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e9c0d61d 6497c7e6
...@@ -240,6 +240,8 @@ static inline int inet_is_local_reserved_port(struct net *net, int port) ...@@ -240,6 +240,8 @@ static inline int inet_is_local_reserved_port(struct net *net, int port)
} }
#endif #endif
__be32 inet_current_timestamp(void);
/* From inetpeer.c */ /* From inetpeer.c */
extern int inet_peer_threshold; extern int inet_peer_threshold;
extern int inet_peer_minttl; extern int inet_peer_minttl;
......
...@@ -1380,6 +1380,32 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, ...@@ -1380,6 +1380,32 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
return pp; return pp;
} }
#define SECONDS_PER_DAY 86400
/* inet_current_timestamp - Return IP network timestamp
*
* Return milliseconds since midnight in network byte order.
*/
__be32 inet_current_timestamp(void)
{
u32 secs;
u32 msecs;
struct timespec64 ts;
ktime_get_real_ts64(&ts);
/* Get secs since midnight. */
(void)div_u64_rem(ts.tv_sec, SECONDS_PER_DAY, &secs);
/* Convert to msecs. */
msecs = secs * MSEC_PER_SEC;
/* Convert nsec to msec. */
msecs += (u32)ts.tv_nsec / NSEC_PER_MSEC;
/* Convert to network byte order. */
return htons(msecs);
}
EXPORT_SYMBOL(inet_current_timestamp);
int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
{ {
if (sk->sk_family == AF_INET) if (sk->sk_family == AF_INET)
......
...@@ -931,7 +931,6 @@ static bool icmp_echo(struct sk_buff *skb) ...@@ -931,7 +931,6 @@ static bool icmp_echo(struct sk_buff *skb)
*/ */
static bool icmp_timestamp(struct sk_buff *skb) static bool icmp_timestamp(struct sk_buff *skb)
{ {
struct timespec tv;
struct icmp_bxm icmp_param; struct icmp_bxm icmp_param;
/* /*
* Too short. * Too short.
...@@ -942,9 +941,7 @@ static bool icmp_timestamp(struct sk_buff *skb) ...@@ -942,9 +941,7 @@ static bool icmp_timestamp(struct sk_buff *skb)
/* /*
* Fill in the current time as ms since midnight UT: * Fill in the current time as ms since midnight UT:
*/ */
getnstimeofday(&tv); icmp_param.data.times[1] = inet_current_timestamp();
icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +
tv.tv_nsec / NSEC_PER_MSEC);
icmp_param.data.times[2] = icmp_param.data.times[1]; icmp_param.data.times[2] = icmp_param.data.times[1];
if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4)) if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))
BUG(); BUG();
......
...@@ -58,10 +58,9 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt, ...@@ -58,10 +58,9 @@ void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
if (opt->ts_needaddr) if (opt->ts_needaddr)
ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt);
if (opt->ts_needtime) { if (opt->ts_needtime) {
struct timespec tv;
__be32 midtime; __be32 midtime;
getnstimeofday(&tv);
midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC); midtime = inet_current_timestamp();
memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4); memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
} }
return; return;
...@@ -415,11 +414,10 @@ int ip_options_compile(struct net *net, ...@@ -415,11 +414,10 @@ int ip_options_compile(struct net *net,
break; break;
} }
if (timeptr) { if (timeptr) {
struct timespec tv; __be32 midtime;
u32 midtime;
getnstimeofday(&tv); midtime = inet_current_timestamp();
midtime = (tv.tv_sec % 86400) * MSEC_PER_SEC + tv.tv_nsec / NSEC_PER_MSEC; memcpy(timeptr, &midtime, 4);
put_unaligned_be32(midtime, timeptr);
opt->is_changed = 1; opt->is_changed = 1;
} }
} else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) { } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
......
...@@ -187,13 +187,13 @@ static int tcpprobe_sprint(char *tbuf, int n) ...@@ -187,13 +187,13 @@ static int tcpprobe_sprint(char *tbuf, int n)
{ {
const struct tcp_log *p const struct tcp_log *p
= tcp_probe.log + tcp_probe.tail; = tcp_probe.log + tcp_probe.tail;
struct timespec tv struct timespec64 ts
= ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start)); = ktime_to_timespec64(ktime_sub(p->tstamp, tcp_probe.start));
return scnprintf(tbuf, n, return scnprintf(tbuf, n,
"%lu.%09lu %pISpc %pISpc %d %#x %#x %u %u %u %u %u\n", "%lu.%09lu %pISpc %pISpc %d %#x %#x %u %u %u %u %u\n",
(unsigned long)tv.tv_sec, (unsigned long)ts.tv_sec,
(unsigned long)tv.tv_nsec, (unsigned long)ts.tv_nsec,
&p->src, &p->dst, p->length, p->snd_nxt, p->snd_una, &p->src, &p->dst, p->length, p->snd_nxt, p->snd_una,
p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd); p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt, p->rcv_wnd);
} }
......
...@@ -65,7 +65,7 @@ static struct { ...@@ -65,7 +65,7 @@ static struct {
struct kfifo fifo; struct kfifo fifo;
spinlock_t lock; spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
struct timespec tstart; struct timespec64 tstart;
} sctpw; } sctpw;
static __printf(1, 2) void printl(const char *fmt, ...) static __printf(1, 2) void printl(const char *fmt, ...)
...@@ -85,7 +85,7 @@ static __printf(1, 2) void printl(const char *fmt, ...) ...@@ -85,7 +85,7 @@ static __printf(1, 2) void printl(const char *fmt, ...)
static int sctpprobe_open(struct inode *inode, struct file *file) static int sctpprobe_open(struct inode *inode, struct file *file)
{ {
kfifo_reset(&sctpw.fifo); kfifo_reset(&sctpw.fifo);
getnstimeofday(&sctpw.tstart); ktime_get_ts64(&sctpw.tstart);
return 0; return 0;
} }
...@@ -138,7 +138,7 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, ...@@ -138,7 +138,7 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
struct sk_buff *skb = chunk->skb; struct sk_buff *skb = chunk->skb;
struct sctp_transport *sp; struct sctp_transport *sp;
static __u32 lcwnd = 0; static __u32 lcwnd = 0;
struct timespec now; struct timespec64 now;
sp = asoc->peer.primary_path; sp = asoc->peer.primary_path;
...@@ -149,8 +149,8 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net, ...@@ -149,8 +149,8 @@ static sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
(full || sp->cwnd != lcwnd)) { (full || sp->cwnd != lcwnd)) {
lcwnd = sp->cwnd; lcwnd = sp->cwnd;
getnstimeofday(&now); ktime_get_ts64(&now);
now = timespec_sub(now, sctpw.tstart); now = timespec64_sub(now, sctpw.tstart);
printl("%lu.%06lu ", (unsigned long) now.tv_sec, printl("%lu.%06lu ", (unsigned long) now.tv_sec,
(unsigned long) now.tv_nsec / NSEC_PER_USEC); (unsigned long) now.tv_nsec / NSEC_PER_USEC);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment