[PATCH 4/9]: Recompute average loss interval

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[TFRC]: Recompute average loss interval

This patch:
 * adds routines for recomputing I_mean/p as required by TFRC;
 * places the average, I_mean, into the loss_hist structure;
 * supports continued detection of new loss intervals.

The second point is in keeping with the objective: loss history management
and computing the relevant data is a service exported by the module. Hence the
module should have exclusive access to the average I_mean which it maintains.

Furthermore, any new packet is monitored against wrap-around of the window
counter with respect to the current loss interval. 
As described in RFC 4342, 10.2, this test is required in order to accurately
determine whether two losses belong to different loss intervals.

Finally, the weights have been re-adjusted to use the format suggested in
[RFC 3448, 5.4]: using the ones of section 8 reduces accuracy ('smoothness');
this could be reverted if people think that there is a gain in using mostly
multiples of two (not too sure there is).

Signed-off-by: Gerrit Renker <gerrit@xxxxxxxxxxxxxx>
---
 net/dccp/ccids/ccid3.h             |    2 
 net/dccp/ccids/lib/loss_interval.c |   87 +++++++++++++++++++++----------------
 net/dccp/ccids/lib/loss_interval.h |    5 +-
 3 files changed, 55 insertions(+), 39 deletions(-)

--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -44,10 +44,12 @@ struct tfrc_loss_interval {
  *  tfrc_loss_hist  -  Loss record database
  *  @ring:	Circular queue managed in LIFO manner
  *  @counter:	Current count of entries (can be more than %LIH_SIZE)
+ *  @i_mean:	Current Average Loss Interval [RFC 3448, 5.4]
  */
 struct tfrc_loss_hist {
 	struct tfrc_loss_interval	*ring[LIH_SIZE];
 	u8				counter;
+	u32				i_mean;
 };
 
 static inline void tfrc_lh_init(struct tfrc_loss_hist *lh)
@@ -65,8 +67,7 @@ static inline u8 tfrc_lh_length(struct t
 	return min(lh->counter, (u8)LIH_SIZE);
 }
 
+extern u8   tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *);
 extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh);
 
-extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
-
 #endif /* _DCCP_LI_HIST_ */
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -158,7 +158,7 @@ struct ccid3_hc_rx_sock {
 	struct tfrc_rx_hist		ccid3hcrx_hist;
 	struct tfrc_loss_hist		ccid3hcrx_li_hist;
 	u16				ccid3hcrx_s;
-	u32				ccid3hcrx_pinv;
+#define ccid3hcrx_pinv			ccid3hcrx_li_hist.i_mean
 };
 
 static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -17,6 +17,8 @@
 #include "loss_interval.h"
 
 static struct kmem_cache  *tfrc_lh_slab;
+/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
+static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
 
 /*
  * Access macros: These require that at least one entry is present in lh,
@@ -59,51 +61,64 @@ void tfrc_lh_cleanup(struct tfrc_loss_hi
 }
 EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
 
-/* Weights used to calculate loss event rate */
-/*
- * These are integers as per section 8 of RFC3448. We can then divide by 4 *
- * when we use it.
- */
-static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = {
-	4, 4, 4, 4, 3, 2, 1, 1,
-};
-
-u32 dccp_li_hist_calc_i_mean(struct list_head *list)
-{
-	struct dccp_li_hist_entry *li_entry, *li_next;
-	int i = 0;
-	u32 i_tot;
-	u32 i_tot0 = 0;
-	u32 i_tot1 = 0;
-	u32 w_tot  = 0;
-
-	list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
-		if (li_entry->dccplih_interval != ~0U) {
-			i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
-			w_tot  += dccp_li_hist_w[i];
-			if (i != 0)
-				i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
-		}
+static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
+{
+	u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0;
+	int i, k = tfrc_lh_length(lh) - 1; /* k is as in rfc3448bis, 5.4 */
 
+	for (i=0; i <= k; i++) {
+		i_i = tfrc_lh_get_interval(lh, i);
 
-		if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
-			break;
+		if (i < k) {
+			i_tot0 += i_i * tfrc_lh_weights[i];
+			w_tot  += tfrc_lh_weights[i];
+		}
+		if (i > 0)
+			i_tot1 += i_i * tfrc_lh_weights[i-1];
 	}
 
-	if (i != DCCP_LI_HIST_IVAL_F_LENGTH)
+	BUG_ON(w_tot == 0);
+	lh->i_mean = max(i_tot0, i_tot1) / w_tot;
+}
+
+/**
+ * tfrc_lh_update_i_mean  -  Update the `open' loss interval I_0
+ * For recomputing p: returns `true' if p > p_prev  <=>  1/p < 1/p_prev
+ */
+u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
+{
+	struct tfrc_loss_interval *cur = tfrc_lh_peek(lh);
+	u32 old_i_mean = lh->i_mean;
+	s64 length;
+
+	if (cur == NULL)			/* not initialised */
 		return 0;
 
-	i_tot = max(i_tot0, i_tot1);
+	length = dccp_delta_seqno(cur->li_seqno, DCCP_SKB_CB(skb)->dccpd_seq);
 
-	if (!w_tot) {
-		DCCP_WARN("w_tot = 0\n");
-		return 1;
-	}
+	if (length - cur->li_length <= 0)	/* duplicate or reordered */
+		return 0;
 
-	return i_tot / w_tot;
-}
+	if (SUB16(dccp_hdr(skb)->dccph_ccval, cur->li_ccval) > 4)
+		/*
+		 * Implements RFC 4342, 10.2:
+		 * If a packet S (skb) exists whose seqno comes `after' the one
+		 * starting the current loss interval (cur) and if the modulo-16
+		 * distance from C(cur) to C(S) is greater than 4, consider all
+		 * subsequent packets as belonging to a new loss interval. This
+		 * test is necessary since CCVal may wrap between intervals.
+		 */
+		cur->li_is_closed = 1;
 
-EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
+	if (tfrc_lh_length(lh) == 1)		/* due to RFC 3448, 6.3.1 */
+		return 0;
+
+	cur->li_length = length;
+	tfrc_lh_calc_i_mean(lh);
+
+	return (lh->i_mean < old_i_mean);
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
 
 int __init li_init(void)
 {
-
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [IETF DCCP]     [Linux Networking]     [Git]     [Security]     [Linux Assembly]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux