[DCCP] Introduce dccp_timestamp

To start the timestamps with 0.0ms, easing the integer maths in the CCIDs, this
probably will be reworked to use the to be introduced struct timeval_offset
infrastructure out of skb_get_timestamp, etc.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 5e0af0d..8bf4bac 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -432,6 +432,7 @@
 	struct ccid			*dccps_hc_rx_ccid;
 	struct ccid			*dccps_hc_tx_ccid;
 	struct dccp_options_received	dccps_options_received;
+	struct timeval			dccps_epoch;
 	enum dccp_role			dccps_role:2;
 	__u8				dccps_hc_rx_insert_options:1;
 	__u8				dccps_hc_tx_insert_options:1;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 145aafa..348e6fb 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -169,7 +169,7 @@
 	} else {
 		struct timeval now;
 
-		do_gettimeofday(&now);
+		dccp_timestamp(sk, &now);
 	       	if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
 		    hctx->ccid3hctx_rtt) {
 			hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
@@ -317,7 +317,7 @@
 		dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
 	}
 
-	do_gettimeofday(&now);
+	dccp_timestamp(sk, &now);
 
 	switch (hctx->ccid3hctx_state) {
 	case TFRC_SSTATE_NO_SENT:
@@ -382,7 +382,7 @@
 		return;
 	}
 
-	do_gettimeofday(&now);
+	dccp_timestamp(sk, &now);
 
 	/* check if we have sent a data packet */
 	if (len > 0) {
@@ -461,6 +461,7 @@
 	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
 	struct ccid3_options_received *opt_recv;
 	struct dccp_tx_hist_entry *packet;
+	struct timeval now;
 	unsigned long next_tmout; 
 	u32 t_elapsed;
 	u32 pinv;
@@ -508,7 +509,8 @@
 		}
 
 		/* Update RTT */
-		r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
+		dccp_timestamp(sk, &now);
+		r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
 		if (unlikely(r_sample <= t_elapsed))
 			LIMIT_NETDEBUG(KERN_WARNING
 				       "%s: r_sample=%uus, t_elapsed=%uus\n",
@@ -774,7 +776,7 @@
 
 	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
-	do_gettimeofday(&now);
+	dccp_timestamp(sk, &now);
 
 	switch (hcrx->ccid3hcrx_state) {
 	case TFRC_RSTATE_NO_DATA:
@@ -903,10 +905,9 @@
 	if (rtt == 0)
 		rtt = 1;
 
-	delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback);
-	x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC;
-	if (likely(delta > 1))
-		x_recv /= delta;
+	dccp_timestamp(sk, &tstamp);
+	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
+	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
 
 	tmp1 = (u64)x_recv * (u64)rtt;
 	do_div(tmp1,10000000);
@@ -981,7 +982,7 @@
 		if (opt_recv->dccpor_timestamp_echo == 0)
 			break;
 		p_prev = hcrx->ccid3hcrx_rtt;
-		do_gettimeofday(&now);
+		dccp_timestamp(sk, &now);
 		timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
 		r_sample = timeval_usecs(&now);
 		t_elapsed = opt_recv->dccpor_elapsed_time * 10;
@@ -1013,7 +1014,7 @@
 		return;
 	}
 
-	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
+	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
 					skb, SLAB_ATOMIC);
 	if (packet == NULL) {
 		ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet "
@@ -1045,7 +1046,7 @@
 		if (ins != 0)
 			break;
 
-		do_gettimeofday(&now);
+		dccp_timestamp(sk, &now);
 		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
 		    hcrx->ccid3hcrx_rtt) {
 			hcrx->ccid3hcrx_tstamp_last_ack = now;
@@ -1100,7 +1101,7 @@
 	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
 	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
 	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
-	do_gettimeofday(&hcrx->ccid3hcrx_tstamp_last_ack);
+	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
 	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
 	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
 	return 0;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index ee8cbac..58be612 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -115,7 +115,7 @@
   	u64			ccid3hcrx_seqno_last_counter:48,
 				ccid3hcrx_state:8,
 				ccid3hcrx_last_counter:4;
-	unsigned long		ccid3hcrx_rtt;
+	u32			ccid3hcrx_rtt;
   	u32			ccid3hcrx_p;
   	u32			ccid3hcrx_bytes_recv;
   	struct timeval		ccid3hcrx_tstamp_last_feedback;
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index fb90a91..b375ebd 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -134,6 +134,7 @@
 
 static inline struct dccp_rx_hist_entry *
 		     dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
+				     	    const struct sock *sk, 
 				     	    const u32 ndp, 
 					    const struct sk_buff *skb,
 					    const unsigned int __nocast prio)
@@ -148,7 +149,7 @@
 		entry->dccphrx_ccval = dh->dccph_ccval;
 		entry->dccphrx_type  = dh->dccph_type;
 		entry->dccphrx_ndp   = ndp;
-		do_gettimeofday(&(entry->dccphrx_tstamp));
+		dccp_timestamp(sk, &entry->dccphrx_tstamp);
 	}
 
 	return entry;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 33456c0..95c4630 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -426,10 +426,13 @@
 		dccp_ackpkts_alloc(unsigned int len,
 				  const unsigned int __nocast priority);
 extern void dccp_ackpkts_free(struct dccp_ackpkts *ap);
-extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state);
+extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+			    u64 ackno, u8 state);
 extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
 					 struct sock *sk, u64 ackno);
 
+extern void dccp_timestamp(const struct sock *sk, struct timeval *tv);
+
 static inline suseconds_t timeval_usecs(const struct timeval *tv)
 {
 	return tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
@@ -468,17 +471,6 @@
 	}
 }
 
-/*
- * Returns the difference in usecs between timeval
- * passed in and current time
- */
-static inline suseconds_t timeval_now_delta(const struct timeval *tv)
-{
-	struct timeval now;
-	do_gettimeofday(&now);
-	return timeval_delta(&now, tv);
-}
-
 #ifdef CONFIG_IP_DCCP_DEBUG
 extern void dccp_ackvector_print(const u64 ackno,
 				 const unsigned char *vector, int len);
diff --git a/net/dccp/input.c b/net/dccp/input.c
index ef29cef..c60bc34 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -170,7 +170,7 @@
 	if (dp->dccps_options.dccpo_send_ack_vector) {
 		struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
 
-		if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
+		if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
 				     DCCP_SKB_CB(skb)->dccpd_seq,
 				     DCCP_ACKPKTS_STATE_RECEIVED)) {
 			LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable "
@@ -498,7 +498,7 @@
 		 * DCCP_ACKPKTS_STATE_ECN_MARKED
 		 */
 		if (dp->dccps_options.dccpo_send_ack_vector) {
-			if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts,
+			if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk,
 					     DCCP_SKB_CB(skb)->dccpd_seq,
 					     DCCP_ACKPKTS_STATE_RECEIVED))
 				goto discard;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 3fc75db..fee9a8c 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -1243,6 +1243,7 @@
 	static int dccp_ctl_socket_init = 1;
 
 	dccp_options_init(&dp->dccps_options);
+	do_gettimeofday(&dp->dccps_epoch);
 
 	if (dp->dccps_options.dccpo_send_ack_vector) {
 		dp->dccps_hc_rx_ackpkts =
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index ce5dff4..18461bc 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -96,6 +96,7 @@
 		newdp->dccps_hc_rx_ackpkts = NULL;
 		newdp->dccps_role = DCCP_ROLE_SERVER;
 		newicsk->icsk_rto = DCCP_TIMEOUT_INIT;
+		do_gettimeofday(&newdp->dccps_epoch);
 
 		if (newdp->dccps_options.dccpo_send_ack_vector) {
 			newdp->dccps_hc_rx_ackpkts =
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 34b230a..d4c4242 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -140,7 +140,7 @@
 			opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
 
 			dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
-			do_gettimeofday(&dp->dccps_timestamp_time);
+			dccp_timestamp(sk, &dp->dccps_timestamp_time);
 
 			dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
 				      debug_prefix, opt_recv->dccpor_timestamp,
@@ -361,9 +361,13 @@
 #endif
 	struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
 	int len = ap->dccpap_buf_vector_len + 2;
-	const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10;
+	struct timeval now;
+	u32 elapsed_time;
 	unsigned char *to, *from;
 
+	dccp_timestamp(sk, &now);
+	elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10;
+
 	if (elapsed_time != 0)
 		dccp_insert_option_elapsed_time(sk, skb, elapsed_time);
 
@@ -428,13 +432,29 @@
 		      (unsigned long long) ap->dccpap_ack_ackno);
 }
 
+void dccp_timestamp(const struct sock *sk, struct timeval *tv)
+{
+	const struct dccp_sock *dp = dccp_sk(sk);
+
+	do_gettimeofday(tv);
+	tv->tv_sec  -= dp->dccps_epoch.tv_sec;
+	tv->tv_usec -= dp->dccps_epoch.tv_usec;
+
+	while (tv->tv_usec < 0) {
+		tv->tv_sec--;
+		tv->tv_usec += USEC_PER_SEC;
+	}
+}
+
+EXPORT_SYMBOL_GPL(dccp_timestamp);
+
 void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
 {
 	struct timeval tv;
 	u32 now;
 	
-	do_gettimeofday(&tv);
-	now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10;
+	dccp_timestamp(sk, &tv);
+	now = timeval_usecs(&tv) / 10;
 	/* yes this will overflow but that is the point as we want a
 	 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
 
@@ -452,13 +472,17 @@
 	const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
 					"CLIENT TX opt: " : "server TX opt: ";
 #endif
+	struct timeval now;
 	u32 tstamp_echo;
-	const u32 elapsed_time =
-			timeval_now_delta(&dp->dccps_timestamp_time) / 10;
-	const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
-	const int len = 6 + elapsed_time_len;
+	u32 elapsed_time;
+	int len, elapsed_time_len;
 	unsigned char *to;
 
+	dccp_timestamp(sk, &now);
+	elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10;
+	elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
+	len = 6 + elapsed_time_len;
+
 	if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
 		LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
 					 "timestamp echo!\n");
@@ -623,7 +647,8 @@
 /*
  * Implements the draft-ietf-dccp-spec-11.txt Appendix A
  */
-int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
+int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk,
+		     u64 ackno, u8 state)
 {
 	/*
 	 * Check at the right places if the buffer is full, if it is, tell the
@@ -704,7 +729,7 @@
 	}
 
 	ap->dccpap_buf_ackno = ackno;
-	do_gettimeofday(&ap->dccpap_time);
+	dccp_timestamp(sk, &ap->dccpap_time);
 out:
 	dccp_pr_debug("");
 	dccp_ackpkts_print(ap);