aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-12 11:23:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:20 -0500
commit3f71c81ac37b27b824e9ce18fe17438dc2af4a16 (patch)
tree0291ca60c033aec233443faec78777f603e5e419
parent954c2db868ce896325dced91d5fba5e2226897a4 (diff)
[TFRC]: Remove previous loss intervals implementation
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/dccp/ccids/lib/loss_interval.c266
-rw-r--r--net/dccp/ccids/lib/loss_interval.h10
2 files changed, 1 insertions, 275 deletions
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 8b962c1f14b8..849e181e698f 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -14,15 +14,6 @@
14#include <net/sock.h> 14#include <net/sock.h>
15#include "tfrc.h" 15#include "tfrc.h"
16 16
17#define DCCP_LI_HIST_IVAL_F_LENGTH 8
18
19struct dccp_li_hist_entry {
20 struct list_head dccplih_node;
21 u64 dccplih_seqno:48,
22 dccplih_win_count:4;
23 u32 dccplih_interval;
24};
25
26static struct kmem_cache *tfrc_lh_slab __read_mostly; 17static struct kmem_cache *tfrc_lh_slab __read_mostly;
27/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */ 18/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
28static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 }; 19static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
@@ -71,77 +62,6 @@ void tfrc_lh_cleanup(struct tfrc_loss_hist *lh)
71} 62}
72EXPORT_SYMBOL_GPL(tfrc_lh_cleanup); 63EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
73 64
74static struct kmem_cache *dccp_li_cachep __read_mostly;
75
76static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
77{
78 return kmem_cache_alloc(dccp_li_cachep, prio);
79}
80
81static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
82{
83 if (entry != NULL)
84 kmem_cache_free(dccp_li_cachep, entry);
85}
86
87void dccp_li_hist_purge(struct list_head *list)
88{
89 struct dccp_li_hist_entry *entry, *next;
90
91 list_for_each_entry_safe(entry, next, list, dccplih_node) {
92 list_del_init(&entry->dccplih_node);
93 kmem_cache_free(dccp_li_cachep, entry);
94 }
95}
96
97EXPORT_SYMBOL_GPL(dccp_li_hist_purge);
98
99/* Weights used to calculate loss event rate */
100/*
101 * These are integers as per section 8 of RFC3448. We can then divide by 4 *
102 * when we use it.
103 */
104static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = {
105 4, 4, 4, 4, 3, 2, 1, 1,
106};
107
108u32 dccp_li_hist_calc_i_mean(struct list_head *list)
109{
110 struct dccp_li_hist_entry *li_entry, *li_next;
111 int i = 0;
112 u32 i_tot;
113 u32 i_tot0 = 0;
114 u32 i_tot1 = 0;
115 u32 w_tot = 0;
116
117 list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
118 if (li_entry->dccplih_interval != ~0U) {
119 i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
120 w_tot += dccp_li_hist_w[i];
121 if (i != 0)
122 i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
123 }
124
125
126 if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
127 break;
128 }
129
130 if (i != DCCP_LI_HIST_IVAL_F_LENGTH)
131 return 0;
132
133 i_tot = max(i_tot0, i_tot1);
134
135 if (!w_tot) {
136 DCCP_WARN("w_tot = 0\n");
137 return 1;
138 }
139
140 return i_tot / w_tot;
141}
142
143EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
144
145static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh) 65static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
146{ 66{
147 u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0; 67 u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0;
@@ -201,192 +121,6 @@ u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
201} 121}
202EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean); 122EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
203 123
204static int dccp_li_hist_interval_new(struct list_head *list,
205 const u64 seq_loss, const u8 win_loss)
206{
207 struct dccp_li_hist_entry *entry;
208 int i;
209
210 for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
211 entry = dccp_li_hist_entry_new(GFP_ATOMIC);
212 if (entry == NULL) {
213 dccp_li_hist_purge(list);
214 DCCP_BUG("loss interval list entry is NULL");
215 return 0;
216 }
217 entry->dccplih_interval = ~0;
218 list_add(&entry->dccplih_node, list);
219 }
220
221 entry->dccplih_seqno = seq_loss;
222 entry->dccplih_win_count = win_loss;
223 return 1;
224}
225
226/* calculate first loss interval
227 *
228 * returns estimated loss interval in usecs */
229static u32 dccp_li_calc_first_li(struct sock *sk,
230 struct list_head *hist_list,
231 ktime_t last_feedback,
232 u16 s, u32 bytes_recv,
233 u32 previous_x_recv)
234{
235/*
236 * FIXME:
237 * Will be rewritten in the upcoming new loss intervals code.
238 * Has to be commented ou because it relies on the old rx history
239 * data structures
240 */
241#if 0
242 struct tfrc_rx_hist_entry *entry, *next, *tail = NULL;
243 u32 x_recv, p;
244 suseconds_t rtt, delta;
245 ktime_t tstamp = ktime_set(0, 0);
246 int interval = 0;
247 int win_count = 0;
248 int step = 0;
249 u64 fval;
250
251 list_for_each_entry_safe(entry, next, hist_list, tfrchrx_node) {
252 if (tfrc_rx_hist_entry_data_packet(entry)) {
253 tail = entry;
254
255 switch (step) {
256 case 0:
257 tstamp = entry->tfrchrx_tstamp;
258 win_count = entry->tfrchrx_ccval;
259 step = 1;
260 break;
261 case 1:
262 interval = win_count - entry->tfrchrx_ccval;
263 if (interval < 0)
264 interval += TFRC_WIN_COUNT_LIMIT;
265 if (interval > 4)
266 goto found;
267 break;
268 }
269 }
270 }
271
272 if (unlikely(step == 0)) {
273 DCCP_WARN("%s(%p), packet history has no data packets!\n",
274 dccp_role(sk), sk);
275 return ~0;
276 }
277
278 if (unlikely(interval == 0)) {
279 DCCP_WARN("%s(%p), Could not find a win_count interval > 0. "
280 "Defaulting to 1\n", dccp_role(sk), sk);
281 interval = 1;
282 }
283found:
284 if (!tail) {
285 DCCP_CRIT("tail is null\n");
286 return ~0;
287 }
288
289 delta = ktime_us_delta(tstamp, tail->tfrchrx_tstamp);
290 DCCP_BUG_ON(delta < 0);
291
292 rtt = delta * 4 / interval;
293 dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
294 dccp_role(sk), sk, (int)rtt);
295
296 /*
297 * Determine the length of the first loss interval via inverse lookup.
298 * Assume that X_recv can be computed by the throughput equation
299 * s
300 * X_recv = --------
301 * R * fval
302 * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
303 */
304 if (rtt == 0) { /* would result in divide-by-zero */
305 DCCP_WARN("RTT==0\n");
306 return ~0;
307 }
308
309 delta = ktime_us_delta(ktime_get_real(), last_feedback);
310 DCCP_BUG_ON(delta <= 0);
311
312 x_recv = scaled_div32(bytes_recv, delta);
313 if (x_recv == 0) { /* would also trigger divide-by-zero */
314 DCCP_WARN("X_recv==0\n");
315 if (previous_x_recv == 0) {
316 DCCP_BUG("stored value of X_recv is zero");
317 return ~0;
318 }
319 x_recv = previous_x_recv;
320 }
321
322 fval = scaled_div(s, rtt);
323 fval = scaled_div32(fval, x_recv);
324 p = tfrc_calc_x_reverse_lookup(fval);
325
326 dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
327 "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
328
329 if (p != 0)
330 return 1000000 / p;
331#endif
332 return ~0;
333}
334
335void dccp_li_update_li(struct sock *sk,
336 struct list_head *li_hist_list,
337 struct list_head *hist_list,
338 ktime_t last_feedback, u16 s, u32 bytes_recv,
339 u32 previous_x_recv, u64 seq_loss, u8 win_loss)
340{
341 struct dccp_li_hist_entry *head;
342 u64 seq_temp;
343
344 if (list_empty(li_hist_list)) {
345 if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
346 win_loss))
347 return;
348
349 head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
350 dccplih_node);
351 head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
352 last_feedback,
353 s, bytes_recv,
354 previous_x_recv);
355 } else {
356 struct dccp_li_hist_entry *entry;
357 struct list_head *tail;
358
359 head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
360 dccplih_node);
361 /* FIXME win count check removed as was wrong */
362 /* should make this check with receive history */
363 /* and compare there as per section 10.2 of RFC4342 */
364
365 /* new loss event detected */
366 /* calculate last interval length */
367 seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
368 entry = dccp_li_hist_entry_new(GFP_ATOMIC);
369
370 if (entry == NULL) {
371 DCCP_BUG("out of memory - can not allocate entry");
372 return;
373 }
374
375 list_add(&entry->dccplih_node, li_hist_list);
376
377 tail = li_hist_list->prev;
378 list_del(tail);
379 kmem_cache_free(dccp_li_cachep, tail);
380
381 /* Create the newest interval */
382 entry->dccplih_seqno = seq_loss;
383 entry->dccplih_interval = seq_temp;
384 entry->dccplih_win_count = win_loss;
385 }
386}
387
388EXPORT_SYMBOL_GPL(dccp_li_update_li);
389
390/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */ 124/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
391static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur, 125static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
392 struct tfrc_rx_hist_entry *new_loss) 126 struct tfrc_rx_hist_entry *new_loss)
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 5e3c5c54a495..246018a3b269 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -65,19 +65,11 @@ static inline u8 tfrc_lh_length(struct tfrc_loss_hist *lh)
65 return min(lh->counter, (u8)LIH_SIZE); 65 return min(lh->counter, (u8)LIH_SIZE);
66} 66}
67 67
68extern void dccp_li_hist_purge(struct list_head *list);
69struct tfrc_rx_hist; 68struct tfrc_rx_hist;
69
70extern int tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *, 70extern int tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *,
71 u32 (*first_li)(struct sock *), struct sock *); 71 u32 (*first_li)(struct sock *), struct sock *);
72extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *); 72extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *);
73extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh); 73extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh);
74 74
75extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
76
77extern void dccp_li_update_li(struct sock *sk,
78 struct list_head *li_hist_list,
79 struct list_head *hist_list,
80 ktime_t last_feedback, u16 s,
81 u32 bytes_recv, u32 previous_x_recv,
82 u64 seq_loss, u8 win_loss);
83#endif /* _DCCP_LI_HIST_ */ 75#endif /* _DCCP_LI_HIST_ */