diff options
author | John W. Linville <linville@tuxdriver.com> | 2006-08-29 16:17:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-08-29 16:17:25 -0400 |
commit | e4ac2663ea27d5dda88d97d117080995fcfcd6d5 (patch) | |
tree | 74eac23956a86546ed93eac973b0bc4744b97ccc /net/dccp/ccids/lib/packet_history.c | |
parent | 4c2be501b7e8695f8bdf4f7d5f51595ed55eea44 (diff) | |
parent | d96299537e43681942ea272e00b0e529aa5b5fa4 (diff) |
Merge branch 'from-linus' into upstream
Diffstat (limited to 'net/dccp/ccids/lib/packet_history.c')
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 168 |
1 files changed, 33 insertions, 135 deletions
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index ad98d6a322eb..b876c9c81c65 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/packet_history.h | 2 | * net/dccp/packet_history.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. |
5 | * | 5 | * |
6 | * An implementation of the DCCP protocol | 6 | * An implementation of the DCCP protocol |
7 | * | 7 | * |
8 | * This code has been developed by the University of Waikato WAND | 8 | * This code has been developed by the University of Waikato WAND |
9 | * research group. For further information please see http://www.wand.net.nz/ | 9 | * research group. For further information please see http://www.wand.net.nz/ |
10 | * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz | 10 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz |
11 | * | 11 | * |
12 | * This code also uses code from Lulea University, rereleased as GPL by its | 12 | * This code also uses code from Lulea University, rereleased as GPL by its |
13 | * authors: | 13 | * authors: |
@@ -112,64 +112,27 @@ struct dccp_rx_hist_entry * | |||
112 | 112 | ||
113 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); | 113 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); |
114 | 114 | ||
115 | int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | 115 | void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, |
116 | struct list_head *rx_list, | 116 | struct list_head *rx_list, |
117 | struct list_head *li_list, | 117 | struct list_head *li_list, |
118 | struct dccp_rx_hist_entry *packet) | 118 | struct dccp_rx_hist_entry *packet, |
119 | u64 nonloss_seqno) | ||
119 | { | 120 | { |
120 | struct dccp_rx_hist_entry *entry, *next, *iter; | 121 | struct dccp_rx_hist_entry *entry, *next; |
121 | u8 num_later = 0; | 122 | u8 num_later = 0; |
122 | 123 | ||
123 | iter = dccp_rx_hist_head(rx_list); | 124 | list_add(&packet->dccphrx_node, rx_list); |
124 | if (iter == NULL) | ||
125 | dccp_rx_hist_add_entry(rx_list, packet); | ||
126 | else { | ||
127 | const u64 seqno = packet->dccphrx_seqno; | ||
128 | |||
129 | if (after48(seqno, iter->dccphrx_seqno)) | ||
130 | dccp_rx_hist_add_entry(rx_list, packet); | ||
131 | else { | ||
132 | if (dccp_rx_hist_entry_data_packet(iter)) | ||
133 | num_later = 1; | ||
134 | |||
135 | list_for_each_entry_continue(iter, rx_list, | ||
136 | dccphrx_node) { | ||
137 | if (after48(seqno, iter->dccphrx_seqno)) { | ||
138 | dccp_rx_hist_add_entry(&iter->dccphrx_node, | ||
139 | packet); | ||
140 | goto trim_history; | ||
141 | } | ||
142 | |||
143 | if (dccp_rx_hist_entry_data_packet(iter)) | ||
144 | num_later++; | ||
145 | 125 | ||
146 | if (num_later == TFRC_RECV_NUM_LATE_LOSS) { | ||
147 | dccp_rx_hist_entry_delete(hist, packet); | ||
148 | return 1; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | if (num_later < TFRC_RECV_NUM_LATE_LOSS) | ||
153 | dccp_rx_hist_add_entry(rx_list, packet); | ||
154 | /* | ||
155 | * FIXME: else what? should we destroy the packet | ||
156 | * like above? | ||
157 | */ | ||
158 | } | ||
159 | } | ||
160 | |||
161 | trim_history: | ||
162 | /* | ||
163 | * Trim history (remove all packets after the NUM_LATE_LOSS + 1 | ||
164 | * data packets) | ||
165 | */ | ||
166 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; | 126 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; |
167 | 127 | ||
168 | if (!list_empty(li_list)) { | 128 | if (!list_empty(li_list)) { |
169 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { | 129 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { |
170 | if (num_later == 0) { | 130 | if (num_later == 0) { |
171 | list_del_init(&entry->dccphrx_node); | 131 | if (after48(nonloss_seqno, |
172 | dccp_rx_hist_entry_delete(hist, entry); | 132 | entry->dccphrx_seqno)) { |
133 | list_del_init(&entry->dccphrx_node); | ||
134 | dccp_rx_hist_entry_delete(hist, entry); | ||
135 | } | ||
173 | } else if (dccp_rx_hist_entry_data_packet(entry)) | 136 | } else if (dccp_rx_hist_entry_data_packet(entry)) |
174 | --num_later; | 137 | --num_later; |
175 | } | 138 | } |
@@ -217,94 +180,10 @@ trim_history: | |||
217 | --num_later; | 180 | --num_later; |
218 | } | 181 | } |
219 | } | 182 | } |
220 | |||
221 | return 0; | ||
222 | } | 183 | } |
223 | 184 | ||
224 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); | 185 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); |
225 | 186 | ||
226 | u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, | ||
227 | struct list_head *li_list, u8 *win_loss) | ||
228 | { | ||
229 | struct dccp_rx_hist_entry *entry, *next, *packet; | ||
230 | struct dccp_rx_hist_entry *a_loss = NULL; | ||
231 | struct dccp_rx_hist_entry *b_loss = NULL; | ||
232 | u64 seq_loss = DCCP_MAX_SEQNO + 1; | ||
233 | u8 num_later = TFRC_RECV_NUM_LATE_LOSS; | ||
234 | |||
235 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { | ||
236 | if (num_later == 0) { | ||
237 | b_loss = entry; | ||
238 | break; | ||
239 | } else if (dccp_rx_hist_entry_data_packet(entry)) | ||
240 | --num_later; | ||
241 | } | ||
242 | |||
243 | if (b_loss == NULL) | ||
244 | goto out; | ||
245 | |||
246 | num_later = 1; | ||
247 | list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { | ||
248 | if (num_later == 0) { | ||
249 | a_loss = entry; | ||
250 | break; | ||
251 | } else if (dccp_rx_hist_entry_data_packet(entry)) | ||
252 | --num_later; | ||
253 | } | ||
254 | |||
255 | if (a_loss == NULL) { | ||
256 | if (list_empty(li_list)) { | ||
257 | /* no loss event have occured yet */ | ||
258 | LIMIT_NETDEBUG("%s: TODO: find a lost data packet by " | ||
259 | "comparing to initial seqno\n", | ||
260 | __FUNCTION__); | ||
261 | goto out; | ||
262 | } else { | ||
263 | LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!", | ||
264 | __FUNCTION__); | ||
265 | goto out; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* Locate a lost data packet */ | ||
270 | entry = packet = b_loss; | ||
271 | list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { | ||
272 | u64 delta = dccp_delta_seqno(entry->dccphrx_seqno, | ||
273 | packet->dccphrx_seqno); | ||
274 | |||
275 | if (delta != 0) { | ||
276 | if (dccp_rx_hist_entry_data_packet(packet)) | ||
277 | --delta; | ||
278 | /* | ||
279 | * FIXME: check this, probably this % usage is because | ||
280 | * in earlier drafts the ndp count was just 8 bits | ||
281 | * long, but now it cam be up to 24 bits long. | ||
282 | */ | ||
283 | #if 0 | ||
284 | if (delta % DCCP_NDP_LIMIT != | ||
285 | (packet->dccphrx_ndp - | ||
286 | entry->dccphrx_ndp) % DCCP_NDP_LIMIT) | ||
287 | #endif | ||
288 | if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) { | ||
289 | seq_loss = entry->dccphrx_seqno; | ||
290 | dccp_inc_seqno(&seq_loss); | ||
291 | } | ||
292 | } | ||
293 | packet = entry; | ||
294 | if (packet == a_loss) | ||
295 | break; | ||
296 | } | ||
297 | out: | ||
298 | if (seq_loss != DCCP_MAX_SEQNO + 1) | ||
299 | *win_loss = a_loss->dccphrx_ccval; | ||
300 | else | ||
301 | *win_loss = 0; /* Paranoia */ | ||
302 | |||
303 | return seq_loss; | ||
304 | } | ||
305 | |||
306 | EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss); | ||
307 | |||
308 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | 187 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) |
309 | { | 188 | { |
310 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | 189 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); |
@@ -365,6 +244,25 @@ struct dccp_tx_hist_entry * | |||
365 | 244 | ||
366 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | 245 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); |
367 | 246 | ||
247 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
248 | u8 *ccval) | ||
249 | { | ||
250 | struct dccp_rx_hist_entry *packet = NULL, *entry; | ||
251 | |||
252 | list_for_each_entry(entry, list, dccphrx_node) | ||
253 | if (entry->dccphrx_seqno == seq) { | ||
254 | packet = entry; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (packet) | ||
259 | *ccval = packet->dccphrx_ccval; | ||
260 | |||
261 | return packet != NULL; | ||
262 | } | ||
263 | |||
264 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
265 | |||
368 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | 266 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, |
369 | struct list_head *list, | 267 | struct list_head *list, |
370 | struct dccp_tx_hist_entry *packet) | 268 | struct dccp_tx_hist_entry *packet) |
@@ -391,7 +289,7 @@ void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | |||
391 | 289 | ||
392 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | 290 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); |
393 | 291 | ||
394 | MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " | 292 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
395 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 293 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
396 | MODULE_DESCRIPTION("DCCP TFRC library"); | 294 | MODULE_DESCRIPTION("DCCP TFRC library"); |
397 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |