diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2007-12-12 11:23:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:57:20 -0500 |
commit | 3f71c81ac37b27b824e9ce18fe17438dc2af4a16 (patch) | |
tree | 0291ca60c033aec233443faec78777f603e5e419 /net/dccp/ccids | |
parent | 954c2db868ce896325dced91d5fba5e2226897a4 (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>
Diffstat (limited to 'net/dccp/ccids')
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.c | 266 | ||||
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.h | 10 |
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 | |||
19 | struct 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 | |||
26 | static struct kmem_cache *tfrc_lh_slab __read_mostly; | 17 | static 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 */ |
28 | static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 }; | 19 | static 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 | } |
72 | EXPORT_SYMBOL_GPL(tfrc_lh_cleanup); | 63 | EXPORT_SYMBOL_GPL(tfrc_lh_cleanup); |
73 | 64 | ||
74 | static struct kmem_cache *dccp_li_cachep __read_mostly; | ||
75 | |||
76 | static 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 | |||
81 | static 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 | |||
87 | void 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 | |||
97 | EXPORT_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 | */ | ||
104 | static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = { | ||
105 | 4, 4, 4, 4, 3, 2, 1, 1, | ||
106 | }; | ||
107 | |||
108 | u32 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 | |||
143 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); | ||
144 | |||
145 | static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh) | 65 | static 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 | } |
202 | EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean); | 122 | EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean); |
203 | 123 | ||
204 | static 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 */ | ||
229 | static 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 | } | ||
283 | found: | ||
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 | |||
335 | void 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 | |||
388 | EXPORT_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] */ |
391 | static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur, | 125 | static 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 | ||
68 | extern void dccp_li_hist_purge(struct list_head *list); | ||
69 | struct tfrc_rx_hist; | 68 | struct tfrc_rx_hist; |
69 | |||
70 | extern int tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *, | 70 | extern 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 *); |
72 | extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *); | 72 | extern u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *); |
73 | extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh); | 73 | extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh); |
74 | 74 | ||
75 | extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); | ||
76 | |||
77 | extern 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_ */ |