diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-27 22:03:09 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 19:12:17 -0400 |
commit | ae6706f0678b89de07ad3b456893cc883584f711 (patch) | |
tree | d9d854ccb0bf7124d98dfaad959f34c11cceef23 /net/dccp/ccids/lib/loss_interval.c | |
parent | cfc3c525a3b434cabf92bf7054f2c6c93497fbea (diff) |
[CCID3]: Move the loss interval code to loss_interval.[ch]
And put this into net/dccp/ccids/lib/, where packet_history.[ch] will also be
moved and then we'll have a tfrc_lib.ko module that will be used by
dccp_ccid3.ko and other CCIDs that are variations of TFRC (RFC 3448).
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/ccids/lib/loss_interval.c')
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c new file mode 100644 index 000000000000..4c01a54143ad --- /dev/null +++ b/net/dccp/ccids/lib/loss_interval.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * net/dccp/ccids/lib/loss_interval.c | ||
3 | * | ||
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | ||
5 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | ||
6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | |||
17 | #include "loss_interval.h" | ||
18 | |||
19 | struct dccp_li_hist *dccp_li_hist_new(const char *name) | ||
20 | { | ||
21 | struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
22 | static const char dccp_li_hist_mask[] = "li_hist_%s"; | ||
23 | char *slab_name; | ||
24 | |||
25 | if (hist == NULL) | ||
26 | goto out; | ||
27 | |||
28 | slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1, | ||
29 | GFP_ATOMIC); | ||
30 | if (slab_name == NULL) | ||
31 | goto out_free_hist; | ||
32 | |||
33 | sprintf(slab_name, dccp_li_hist_mask, name); | ||
34 | hist->dccplih_slab = kmem_cache_create(slab_name, | ||
35 | sizeof(struct dccp_li_hist_entry), | ||
36 | 0, SLAB_HWCACHE_ALIGN, | ||
37 | NULL, NULL); | ||
38 | if (hist->dccplih_slab == NULL) | ||
39 | goto out_free_slab_name; | ||
40 | out: | ||
41 | return hist; | ||
42 | out_free_slab_name: | ||
43 | kfree(slab_name); | ||
44 | out_free_hist: | ||
45 | kfree(hist); | ||
46 | hist = NULL; | ||
47 | goto out; | ||
48 | } | ||
49 | |||
50 | EXPORT_SYMBOL_GPL(dccp_li_hist_new); | ||
51 | |||
52 | void dccp_li_hist_delete(struct dccp_li_hist *hist) | ||
53 | { | ||
54 | const char* name = kmem_cache_name(hist->dccplih_slab); | ||
55 | |||
56 | kmem_cache_destroy(hist->dccplih_slab); | ||
57 | kfree(name); | ||
58 | kfree(hist); | ||
59 | } | ||
60 | |||
61 | EXPORT_SYMBOL_GPL(dccp_li_hist_delete); | ||
62 | |||
63 | void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list) | ||
64 | { | ||
65 | struct dccp_li_hist_entry *entry, *next; | ||
66 | |||
67 | list_for_each_entry_safe(entry, next, list, dccplih_node) { | ||
68 | list_del_init(&entry->dccplih_node); | ||
69 | kmem_cache_free(hist->dccplih_slab, entry); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | EXPORT_SYMBOL_GPL(dccp_li_hist_purge); | ||
74 | |||
75 | /* Weights used to calculate loss event rate */ | ||
76 | /* | ||
77 | * These are integers as per section 8 of RFC3448. We can then divide by 4 * | ||
78 | * when we use it. | ||
79 | */ | ||
80 | static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = { | ||
81 | 4, 4, 4, 4, 3, 2, 1, 1, | ||
82 | }; | ||
83 | |||
84 | u32 dccp_li_hist_calc_i_mean(struct list_head *list) | ||
85 | { | ||
86 | struct dccp_li_hist_entry *li_entry, *li_next; | ||
87 | int i = 0; | ||
88 | u32 i_tot; | ||
89 | u32 i_tot0 = 0; | ||
90 | u32 i_tot1 = 0; | ||
91 | u32 w_tot = 0; | ||
92 | |||
93 | list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { | ||
94 | if (i < DCCP_LI_HIST_IVAL_F_LENGTH) { | ||
95 | i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; | ||
96 | w_tot += dccp_li_hist_w[i]; | ||
97 | } | ||
98 | |||
99 | if (i != 0) | ||
100 | i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; | ||
101 | |||
102 | if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | if (i != DCCP_LI_HIST_IVAL_F_LENGTH) | ||
107 | return 0; | ||
108 | |||
109 | i_tot = max(i_tot0, i_tot1); | ||
110 | |||
111 | /* FIXME: Why do we do this? -Ian McDonald */ | ||
112 | if (i_tot * 4 < w_tot) | ||
113 | i_tot = w_tot * 4; | ||
114 | |||
115 | return i_tot * 4 / w_tot; | ||
116 | } | ||
117 | |||
118 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); | ||
119 | |||
120 | struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist, | ||
121 | struct list_head *list, | ||
122 | const u64 seq_loss, | ||
123 | const u8 win_loss) | ||
124 | { | ||
125 | struct dccp_li_hist_entry *tail = NULL, *entry; | ||
126 | int i; | ||
127 | |||
128 | for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) { | ||
129 | entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); | ||
130 | if (entry == NULL) { | ||
131 | dccp_li_hist_purge(hist, list); | ||
132 | return NULL; | ||
133 | } | ||
134 | if (tail == NULL) | ||
135 | tail = entry; | ||
136 | list_add(&entry->dccplih_node, list); | ||
137 | } | ||
138 | |||
139 | entry->dccplih_seqno = seq_loss; | ||
140 | entry->dccplih_win_count = win_loss; | ||
141 | return tail; | ||
142 | } | ||
143 | |||
144 | EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); | ||