DCCP protocol discussions
 help / color / mirror / Atom feed
* [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi
@ 2006-12-28  4:08 Ian McDonald
  2007-01-03 12:06 ` Gerrit Renker
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Ian McDonald @ 2006-12-28  4:08 UTC (permalink / raw)
  To: dccp

When we recalculate t_nom and t_ipi we should check that t_nom is not
before the current time. If it is then we should set t_nom to current time.

Found this by observing flood of packets when t_ipi decreases.

Also uninline the function as it is big and gcc should decide when to
inline anyway.

Modified this from last iteration by only recalculate if t_ipi drops to
save expensive operations on time.

Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
---
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index e93bae5..ea22d08 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -84,8 +84,12 @@ static void ccid3_hc_tx_set_state(struct sock *sk,
  * Recalculate scheduled nominal send time t_nom, inter-packet interval
  * t_ipi, and delta value. Should be called after each change to X.
  */
-static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
+static void ccid3_update_send_time(struct sock *sk)
 {
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+	suseconds_t delay;
+	u32 old_t_ipi = hctx->ccid3hctx_t_ipi;
+
 	timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
 
 	/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
@@ -103,6 +107,18 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
 	               hctx->ccid3hctx_t_ipi, hctx->ccid3hctx_delta,
 		       hctx->ccid3hctx_s, hctx->ccid3hctx_x >> 6);
 
+	if (old_t_ipi > hctx->ccid3hctx_t_ipi) {
+		struct timeval now;
+		dccp_timestamp(sk, &now);
+
+		/* we want to check if before current time so we don't send a
+		 * flood of packets */
+		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+		if (delay < 0) {
+			hctx->ccid3hctx_t_nom = now;
+			ccid3_pr_debug("reset t_nom\n");
+		}
+	}
 }
 /*
  * Update X by
@@ -149,7 +165,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
 		ccid3_pr_debug("X_prev=%llu, X_now=%llu, X_calc=%u, "
 		               "X_recv=%llu\n", old_x, hctx->ccid3hctx_x,
 			       hctx->ccid3hctx_x_calc, hctx->ccid3hctx_x_recv);
-		ccid3_update_send_time(hctx);
+		ccid3_update_send_time(sk);
 	}
 }
 
@@ -226,7 +242,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
 		/* The value of R is still undefined and so we can not recompute
 		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
 		t_nfb = TFRC_INITIAL_TIMEOUT;
-		ccid3_update_send_time(hctx);
+		ccid3_update_send_time(sk);
 		break;
 	case TFRC_SSTATE_FBACK:
 		/*
@@ -485,7 +501,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 			hctx->ccid3hctx_x    = scaled_div(w_init << 6, r_sample);
 			hctx->ccid3hctx_t_ld = now;
 
-			ccid3_update_send_time(hctx);
+			ccid3_update_send_time(sk);
 
 			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, w_init=%u, "
 				       "R_sample=%dus, X=%u\n", dccp_role(sk),

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi
  2006-12-28  4:08 [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi Ian McDonald
@ 2007-01-03 12:06 ` Gerrit Renker
  2007-01-06 20:36 ` Ian McDonald
  2007-01-08 10:32 ` Gerrit Renker
  2 siblings, 0 replies; 4+ messages in thread
From: Gerrit Renker @ 2007-01-03 12:06 UTC (permalink / raw)
  To: dccp

Ian is right that there is a problem, but this fixes one symptom, but there are
two causes, which are not resolved by this patch:

 (1) t_nom becoming negative is caused by tardiness in packet scheduling
     and therefore it should be resolved at the location which deals with packet
     sending (ccid3_hc_tx_send_packet), and not in ccid3_update_send_time()

 (2) Using this routine carries with it a race condition: several functions
     (ccid3_hc_tx_send_packet, this routine, ccid3_hc_tx_update_x, ccid3_hc_tx_packet_recv)
     have asynchronous, concurrent read-write access to t_nom. 

Please see earlier discussion on `tardiness bug' and the detailed analysis provided with
the `race condition' patch.

Gerrit

Quoting Ian McDonald:
|  diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
|  index e93bae5..ea22d08 100644
|  --- a/net/dccp/ccids/ccid3.c
|  +++ b/net/dccp/ccids/ccid3.c
|  @@ -84,8 +84,12 @@ static void ccid3_hc_tx_set_state(struct sock *sk,
|    * Recalculate scheduled nominal send time t_nom, inter-packet interval
|    * t_ipi, and delta value. Should be called after each change to X.
|    */
|  -static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
|  +static void ccid3_update_send_time(struct sock *sk)
|   {
|  +	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
|  +	suseconds_t delay;
|  +	u32 old_t_ipi = hctx->ccid3hctx_t_ipi;
|  +
|   	timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
|   
|   	/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
|  @@ -103,6 +107,18 @@ static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
|   	               hctx->ccid3hctx_t_ipi, hctx->ccid3hctx_delta,
|   		       hctx->ccid3hctx_s, hctx->ccid3hctx_x >> 6);
|   
|  +	if (old_t_ipi > hctx->ccid3hctx_t_ipi) {
|  +		struct timeval now;
|  +		dccp_timestamp(sk, &now);
|  +
|  +		/* we want to check if before current time so we don't send a
|  +		 * flood of packets */
|  +		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
|  +		if (delay < 0) {
|  +			hctx->ccid3hctx_t_nom = now;
|  +			ccid3_pr_debug("reset t_nom\n");
|  +		}
|  +	}
|   }
|   /*
|    * Update X by
|  @@ -149,7 +165,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)
|   		ccid3_pr_debug("X_prev=%llu, X_now=%llu, X_calc=%u, "
|   		               "X_recv=%llu\n", old_x, hctx->ccid3hctx_x,
|   			       hctx->ccid3hctx_x_calc, hctx->ccid3hctx_x_recv);
|  -		ccid3_update_send_time(hctx);
|  +		ccid3_update_send_time(sk);
|   	}
|   }
|   
|  @@ -226,7 +242,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
|   		/* The value of R is still undefined and so we can not recompute
|   		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
|   		t_nfb = TFRC_INITIAL_TIMEOUT;
|  -		ccid3_update_send_time(hctx);
|  +		ccid3_update_send_time(sk);
|   		break;
|   	case TFRC_SSTATE_FBACK:
|   		/*
|  @@ -485,7 +501,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
|   			hctx->ccid3hctx_x    = scaled_div(w_init << 6, r_sample);
|   			hctx->ccid3hctx_t_ld = now;
|   
|  -			ccid3_update_send_time(hctx);
|  +			ccid3_update_send_time(sk);
|   
|   			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, w_init=%u, "
|   				       "R_sample=%dus, X=%u\n", dccp_role(sk),
|  -
|  To unsubscribe from this list: send the line "unsubscribe dccp" in
|  the body of a message to majordomo@vger.kernel.org
|  More majordomo info at  http://vger.kernel.org/majordomo-info.html
|  
|  

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi
  2006-12-28  4:08 [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi Ian McDonald
  2007-01-03 12:06 ` Gerrit Renker
@ 2007-01-06 20:36 ` Ian McDonald
  2007-01-08 10:32 ` Gerrit Renker
  2 siblings, 0 replies; 4+ messages in thread
From: Ian McDonald @ 2007-01-06 20:36 UTC (permalink / raw)
  To: dccp

On 1/4/07, Gerrit Renker <gerrit@erg.abdn.ac.uk> wrote:
> Ian is right that there is a problem, but this fixes one symptom, but there are
> two causes, which are not resolved by this patch:
>
>  (1) t_nom becoming negative is caused by tardiness in packet scheduling
>      and therefore it should be resolved at the location which deals with packet
>      sending (ccid3_hc_tx_send_packet), and not in ccid3_update_send_time()
>
I thought my solution was better. I originally implemented the same
solution as you and then realised this point 1 you discuss. But it
should be negative in these cases as per RFC 3448 4.6

When a sender first starts sending at time t_0, it calculates t_ipi,
   and calculates a nominal send time t_1 = t_0 + t_ipi for packet 1.
   When the application becomes idle, it checks the current time, t_now,
   and then requests re-scheduling after (t_ipi - (t_now - t_0))
   seconds.  When the application is re-scheduled, it checks the current
   time, t_now, again.  If (t_now > t_1 - delta) then packet 1 is sent.

   Now a new t_ipi may be calculated, and used to calculate a nominal
   send time t_2 for packet 2: t2 = t_1 + t_ipi.  The process then
   repeats, with each successive packet's send time being calculated
   from the nominal send time of the previous packet.

   In some cases, when the nominal send time, t_i, of the next packet is
   calculated, it may already be the case that t_now > t_i - delta.  In
   such a case the packet should be sent immediately.  Thus if the
   operating system has coarse timer granularity and the transmit rate

   is high, then TFRC may send short bursts of several packets separated
   by intervals of the OS timer granularity.

Note there that several packets can be sent in bursts. Your code stops
this and slows transmit down quite a lot.

However I think now my solution is not perfect. What I was trying to
work around and fix was that the t_ipi gets altered down from 1
second.

However thinking about it some more we are doing this the wrong way
altogether and should do it in the sending loop ONLY as per the
suggestion (not requirement) at the top of section 4.6

   As TFRC is rate-based, and as operating systems typically cannot
   schedule events precisely, it is necessary to be opportunistic about
   sending data packets so that the correct average rate is maintained
   despite the course-grain or irregular scheduling of the operating
   system.  Thus a typical sending loop will calculate the correct
   inter-packet interval, t_ipi, as follows:

        t_ipi = s/X_inst;

The special case that we need to deal with is this one from section 5
of RFC4342:
   [RFC3448], Section 4, specifies an initial sending rate of one packet
   per round-trip time (RTT) as follows: The sender initializes the
   allowed sending rate to one packet per second.  As soon as a feedback
   packet is received from the receiver, the sender has a measurement of
   the round-trip time and then sets the initial allowed sending rate to
   one packet per RTT.

>  (2) Using this routine carries with it a race condition: several functions
>      (ccid3_hc_tx_send_packet, this routine, ccid3_hc_tx_update_x, ccid3_hc_tx_packet_recv)
>      have asynchronous, concurrent read-write access to t_nom.
>
> Please see earlier discussion on `tardiness bug' and the detailed analysis provided with
> the `race condition' patch.
>
I think that rewriting this code as per point 1 will eliminate this
problem provided we do it properly.

So the short answer is we both made improvements but we've both got it
not quite right and we need to revise again.

Ian
-- 
Web: http://wand.net.nz/~iam4
Blog: http://imcdnzl.blogspot.com
WAND Network Research Group

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi
  2006-12-28  4:08 [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi Ian McDonald
  2007-01-03 12:06 ` Gerrit Renker
  2007-01-06 20:36 ` Ian McDonald
@ 2007-01-08 10:32 ` Gerrit Renker
  2 siblings, 0 replies; 4+ messages in thread
From: Gerrit Renker @ 2007-01-08 10:32 UTC (permalink / raw)
  To: dccp

|  > there are two causes, which are not resolved by this patch:
|  >
|  >  (1) t_nom becoming negative is caused by tardiness in packet scheduling
|  >      and therefore it should be resolved at the location which deals with packet
|  >      sending (ccid3_hc_tx_send_packet), and not in ccid3_update_send_time()
|  >
|  I thought my solution was better. I originally implemented the same
|  solution as you and then realised this point 1 you discuss. But it
|  should be negative in these cases as per RFC 3448 4.6
|  
|  When a sender first starts sending at time t_0, it calculates t_ipi,
We have had this discussion in detail before, please see
http://www.mail-archive.com/dccp@vger.kernel.org/msg00841.html

  
|  Note there that several packets can be sent in bursts. Your code stops
|  this and slows transmit down quite a lot.
Under which conditions are packets sent in bursts? 

RFC 3448, 4.6 considers coarse timer granularity. However, the problem considered here
is when a packet is scheduled for sending after it was due - tardiness. 

You are saying that my "code stops this and slows transmit down quite a lot". 
This is not true:
 * when tardiness does not occur and packet scheduling is always within bounds, 
   the issue does not arise - we are doing as the RFC says.
 * when tardiness occurs then it is a problem of the packet scheduling engine, but
   not of the calculation of t_ipi. 
In simple terms, tardiness is either a bug (when occurs constantly) or it is an overload
indicator. What my patch does is avoid further damage when such a condition occurs and there
is no doubt here that it should.
What you are proposing above is that reacting to an error condition stops sending a burst of
packets and that therefore it "slows transmit down quite a lot". 
I am not convinced since your argumentation is only valid if the bug/overload case occurs. My
suggestion is to add a warning message when tardiness occurs, but not try to fix a possible
bug/overload condition by changing the way t_ipi is calculated.

|  
|  However I think now my solution is not perfect. What I was trying to
|  work around and fix was that the t_ipi gets altered down from 1
|  second.
Sorry I don't get the reason for this. 
  
|  However thinking about it some more we are doing this the wrong way
|  altogether and should do it in the sending loop ONLY as per the
|  suggestion (not requirement) at the top of section 4.6
Please have a look at the other patch which fixes the race condition; indeed it
makes sure that t_nom is only updated in the sending loop. With regard to t_ipi, 
it is best to update it as soon as new data becomes available.

  
|  The special case that we need to deal with is this one from section 5
|  of RFC4342:
|     [RFC3448], Section 4, specifies an initial sending rate of one packet
|     per round-trip time (RTT) as follows: The sender initializes the
|     allowed sending rate to one packet per second.  As soon as a feedback
|     packet is received from the receiver, the sender has a measurement of
|     the round-trip time and then sets the initial allowed sending rate to
|     one packet per RTT.
This has been done already - support for larger initial windows in hc_tx_packet_recv.


|  
|  >  (2) Using this routine carries with it a race condition: several functions
|  >      (ccid3_hc_tx_send_packet, this routine, ccid3_hc_tx_update_x, ccid3_hc_tx_packet_recv)
|  >      have asynchronous, concurrent read-write access to t_nom.
|  >
|  > Please see earlier discussion on `tardiness bug' and the detailed analysis provided with
|  > the `race condition' patch.
|  >
|  I think that rewriting this code as per point 1 will eliminate this
|  problem provided we do it properly.
|  
|  So the short answer is we both made improvements but we've both got it
|  not quite right and we need to revise again.
I remain to be convinced where we "got it not quite right": we need to catch the bug/overload
condition and we must ensure that race conditions are avoided. Both are taken care of by the
patches I sent. 

Sorry I fail to see what problem you are trying to fix. Of course, it is regrettable when bursts
of packets can not be sent due to tardiness. But, as already explained above, this condition only
appears when there is either (i) a bug in the scheduling engine or (ii) an overload condition.

While I think that (i) is unlikely; if it occurs then we need to reconsider the packet scheduling
(dccp_wait_for_ccid, dccp_write_xmit_timer and related functions), but not the code to calculate
t_nom and t_ipi.

In case (ii) sending bursts of packets is not possible anyhow, since the OS/NIC/network first needs
to recover from the overload condition.

Hence the only point where I agree with you is to add a warning message whenever the tardiness condition
occurs in hc_tx_send_packet, to see whether (i) holds. I am NOT in support of code to deal with (ii).

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-01-08 10:32 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-28  4:08 [PATCH 4/4] DCCP: Recalculate t_nom on change of t_ipi Ian McDonald
2007-01-03 12:06 ` Gerrit Renker
2007-01-06 20:36 ` Ian McDonald
2007-01-08 10:32 ` Gerrit Renker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox