Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6 
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 007c290..8bf4bac 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -432,7 +432,10 @@
 	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;
 };
  
 static inline struct dccp_sock *dccp_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 7bf3b3a..ea30012d 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -43,12 +43,22 @@
 #include "ccid3.h"
 
 /*
- * Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
+ * Reason for maths here is to avoid 32 bit overflow when a is big.
+ * With this we get close to the limit.
  */
 static inline u32 usecs_div(const u32 a, const u32 b)
 {
-	const u32 tmp = a * (USEC_PER_SEC / 10);
-	return b > 20 ? tmp / (b / 10) : tmp;
+	const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
+			a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
+			a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
+			a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
+			a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
+			a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
+			a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
+			a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
+								 100000;
+	const u32 tmp = a * (USEC_PER_SEC / div);
+	return (b >= 2 * div) ? tmp / (b / div) : tmp;
 }
 
 static int ccid3_debug;
@@ -102,8 +112,7 @@
 static inline void ccid3_hc_tx_set_state(struct sock *sk,
 					 enum ccid3_hc_tx_states state)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
 
 	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
@@ -144,8 +153,7 @@
  */ 
 static void ccid3_hc_tx_update_x(struct sock *sk)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
 	/* To avoid large error in calcX */
 	if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
@@ -159,7 +167,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,
@@ -174,9 +182,8 @@
 static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
 {
 	struct sock *sk = (struct sock *)data;
-	struct dccp_sock *dp = dccp_sk(sk);
 	unsigned long next_tmout = 0;
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
 	bh_lock_sock(sk);
 	if (sock_owned_by_user(sk)) {
@@ -274,7 +281,7 @@
 				   struct sk_buff *skb, int len)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct dccp_tx_hist_entry *new_packet;
 	struct timeval now;
 	long delay;
@@ -307,7 +314,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:
@@ -348,18 +355,20 @@
 	}
 
 	/* Can we send? if so add options and add to packet history */
-	if (rc == 0)
+	if (rc == 0) {
+		dp->dccps_hc_tx_insert_options = 1;
 		new_packet->dccphtx_ccval =
 			DCCP_SKB_CB(skb)->dccpd_ccval =
 				hctx->ccid3hctx_last_win_count;
+	}
 out:
 	return rc;
 }
 
 static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	const struct dccp_sock *dp = dccp_sk(sk);
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct timeval now;
 
 	BUG_ON(hctx == NULL);
@@ -370,7 +379,7 @@
 		return;
 	}
 
-	do_gettimeofday(&now);
+	dccp_timestamp(sk, &now);
 
 	/* check if we have sent a data packet */
 	if (len > 0) {
@@ -445,10 +454,11 @@
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	const struct dccp_sock *dp = dccp_sk(sk);
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct ccid3_options_received *opt_recv;
 	struct dccp_tx_hist_entry *packet;
+	struct timeval now;
 	unsigned long next_tmout; 
 	u32 t_elapsed;
 	u32 pinv;
@@ -471,7 +481,7 @@
 
 	opt_recv = &hctx->ccid3hctx_options_received;
 
-	t_elapsed = dp->dccps_options_received.dccpor_elapsed_time;
+	t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
 	x_recv = opt_recv->ccid3or_receive_rate;
 	pinv = opt_recv->ccid3or_loss_event_rate;
 
@@ -496,9 +506,14 @@
 		}
 
 		/* Update RTT */
-		r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
-		/* FIXME: */
-		// r_sample -= usecs_to_jiffies(t_elapsed * 10);
+		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",
+				       __FUNCTION__, r_sample, t_elapsed);
+		else
+			r_sample -= t_elapsed;
 
 		/* Update RTT estimate by 
 		 * If (No feedback recv)
@@ -591,8 +606,7 @@
 
 static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
 	if (hctx == NULL || !(sk->sk_state == DCCP_OPEN ||
 			      sk->sk_state == DCCP_PARTOPEN))
@@ -606,8 +620,8 @@
 				     unsigned char *value)
 {
 	int rc = 0;
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	const struct dccp_sock *dp = dccp_sk(sk);
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 	struct ccid3_options_received *opt_recv;
 
 	if (hctx == NULL)
@@ -670,11 +684,11 @@
 
 	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
-	hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx),
-						      gfp_any());
-	if (hctx == NULL)
+	dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
+	if (dp->dccps_hc_tx_ccid_private == NULL)
 		return -ENOMEM;
 
+	hctx = ccid3_hc_tx_sk(sk);
 	memset(hctx, 0, sizeof(*hctx));
 
 	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
@@ -696,7 +710,7 @@
 static void ccid3_hc_tx_exit(struct sock *sk)
 {
 	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
 	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 	BUG_ON(hctx == NULL);
@@ -738,8 +752,7 @@
 static inline void ccid3_hc_rx_set_state(struct sock *sk,
 					 enum ccid3_hc_rx_states state)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
 
 	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
@@ -751,14 +764,14 @@
 
 static void ccid3_hc_rx_send_feedback(struct sock *sk)
 {
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 	struct dccp_rx_hist_entry *packet;
 	struct timeval now;
 
 	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:
@@ -767,11 +780,8 @@
 	case TFRC_RSTATE_DATA: {
 		const u32 delta = timeval_delta(&now,
 					&hcrx->ccid3hcrx_tstamp_last_feedback);
-
-		hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
-					  USEC_PER_SEC);
-		if (likely(delta > 1))
-			hcrx->ccid3hcrx_x_recv /= delta;
+		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
+						   delta);
 	}
 		break;
 	default:
@@ -801,14 +811,14 @@
 		hcrx->ccid3hcrx_pinv = ~0;
 	else
 		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
+	dp->dccps_hc_rx_insert_options = 1;
 	dccp_send_ack(sk);
 }
 
 static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	u32 x_recv, pinv;
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 
 	if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN ||
 			      sk->sk_state == DCCP_PARTOPEN))
@@ -837,8 +847,7 @@
 
 static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
 	u32 rtt, delta, x_recv, fval, p, tmp2;
 	struct timeval tstamp = { 0, };
@@ -889,10 +898,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);
@@ -911,8 +919,7 @@
 
 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 
 	if (seq_loss != DCCP_MAX_SEQNO + 1 &&
 	    list_empty(&hcrx->ccid3hcrx_li_hist)) {
@@ -930,8 +937,7 @@
 
 static void ccid3_hc_rx_detect_loss(struct sock *sk)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	u8 win_loss;
 	const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
 						      &hcrx->ccid3hcrx_li_hist,
@@ -942,13 +948,12 @@
 
 static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	const struct dccp_options_received *opt_recv;
 	struct dccp_rx_hist_entry *packet;
 	struct timeval now;
 	u8 win_count;
-	u32 p_prev;
+	u32 p_prev, r_sample, t_elapsed;
 	int ins;
 
 	if (hcrx == NULL)
@@ -957,7 +962,7 @@
 	BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
 		 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
 
-	opt_recv = &dp->dccps_options_received;
+	opt_recv = &dccp_sk(sk)->dccps_options_received;
 
 	switch (DCCP_SKB_CB(skb)->dccpd_type) {
 	case DCCP_PKT_ACK:
@@ -967,10 +972,24 @@
 		if (opt_recv->dccpor_timestamp_echo == 0)
 			break;
 		p_prev = hcrx->ccid3hcrx_rtt;
-		do_gettimeofday(&now);
-		hcrx->ccid3hcrx_rtt = timeval_usecs(&now) -
-				     (opt_recv->dccpor_timestamp_echo -
-				      opt_recv->dccpor_elapsed_time) * 10;
+		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;
+
+		if (unlikely(r_sample <= t_elapsed))
+			LIMIT_NETDEBUG(KERN_WARNING
+				       "%s: r_sample=%uus, t_elapsed=%uus\n",
+				       __FUNCTION__, r_sample, t_elapsed);
+		else
+			r_sample -= t_elapsed;
+
+		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
+			hcrx->ccid3hcrx_rtt = r_sample;
+		else
+			hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
+					      r_sample / 10;
+
 		if (p_prev != hcrx->ccid3hcrx_rtt)
 			ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
 				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
@@ -985,7 +1004,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 "
@@ -1017,7 +1036,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;
@@ -1056,11 +1075,11 @@
 
 	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
-	hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx),
-						      gfp_any());
-	if (hcrx == NULL)
+	dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
+	if (dp->dccps_hc_rx_ccid_private == NULL)
 		return -ENOMEM;
 
+	hcrx = ccid3_hc_rx_sk(sk);
 	memset(hcrx, 0, sizeof(*hcrx));
 
 	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
@@ -1072,18 +1091,16 @@
 	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
 	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
 	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
-	/*
-	 * XXX this seems to be paranoid, need to think more about this, for
-	 * now start with something different than zero. -acme
-	 */
-	hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
+	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;
 }
 
 static void ccid3_hc_rx_exit(struct sock *sk)
 {
+	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
-	struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
 
 	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
 
@@ -1104,8 +1121,7 @@
 
 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
-	const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
+	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
 
 	if (hcrx == NULL)
 		return;
@@ -1117,8 +1133,7 @@
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
 {
-	const struct dccp_sock *dp = dccp_sk(sk);
-	const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
+	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
 
 	if (hctx == NULL)
 		return;
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index ee8cbac..d16f00d 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;
@@ -128,10 +128,14 @@
   	u32			ccid3hcrx_x_recv;
 };
 
-#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \
-    ((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field)
+static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
+{
+    return dccp_sk(sk)->dccps_hc_tx_ccid_private;
+}
 
-#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \
-    ((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field)
+static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
+{
+    return dccp_sk(sk)->dccps_hc_rx_ccid_private;
+}
 
 #endif /* _DCCP_CCID3_H_ */
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..95c4630b 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 382c589..d4c4242 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -72,6 +72,7 @@
 	struct dccp_options_received *opt_recv = &dp->dccps_options_received;
 	unsigned char opt, len;
 	unsigned char *value;
+	u32 elapsed_time;
 
 	memset(opt_recv, 0, sizeof(*opt_recv));
 
@@ -139,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,
@@ -159,18 +160,18 @@
 				      (unsigned long long)
 				      DCCP_SKB_CB(skb)->dccpd_ack_seq);
 
-			if (len > 4) {
-				if (len == 6)
-					opt_recv->dccpor_elapsed_time =
-						 ntohs(*(u16 *)(value + 4));
-				else
-					opt_recv->dccpor_elapsed_time =
-						 ntohl(*(u32 *)(value + 4));
 
-				dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n",
-				      debug_prefix,
-				      opt_recv->dccpor_elapsed_time);
-			}
+			if (len == 4)
+				break;
+
+			if (len == 6)
+				elapsed_time = ntohs(*(u16 *)(value + 4));
+			else
+				elapsed_time = ntohl(*(u32 *)(value + 4));
+
+			/* Give precedence to the biggest ELAPSED_TIME */
+			if (elapsed_time > opt_recv->dccpor_elapsed_time)
+				opt_recv->dccpor_elapsed_time = elapsed_time;
 			break;
 		case DCCPO_ELAPSED_TIME:
 			if (len != 2 && len != 4)
@@ -180,14 +181,15 @@
 				continue;
 
 			if (len == 2)
-				opt_recv->dccpor_elapsed_time =
-							ntohs(*(u16 *)value);
+				elapsed_time = ntohs(*(u16 *)value);
 			else
-				opt_recv->dccpor_elapsed_time =
-							ntohl(*(u32 *)value);
+				elapsed_time = ntohl(*(u32 *)value);
+
+			if (elapsed_time > opt_recv->dccpor_elapsed_time)
+				opt_recv->dccpor_elapsed_time = elapsed_time;
 
 			dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
-				      opt_recv->dccpor_elapsed_time);
+				      elapsed_time);
 			break;
 			/*
 			 * From draft-ietf-dccp-spec-11.txt:
@@ -359,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);
 
@@ -426,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 */
 
@@ -450,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");
@@ -505,13 +531,18 @@
 		    (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno !=
 		     DCCP_MAX_SEQNO + 1))
 			dccp_insert_option_ack_vector(sk, skb);
-
 		if (dp->dccps_timestamp_echo != 0)
 			dccp_insert_option_timestamp_echo(sk, skb);
 	}
 
-	ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
-	ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+	if (dp->dccps_hc_rx_insert_options) {
+		ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
+		dp->dccps_hc_rx_insert_options = 0;
+	}
+	if (dp->dccps_hc_tx_insert_options) {
+		ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+		dp->dccps_hc_tx_insert_options = 0;
+	}
 
 	/* XXX: insert other options when appropriate */
 
@@ -616,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
@@ -697,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);