diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2007-11-28 08:15:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:11 -0500 |
commit | 276f2edc52e309b38a216245952e05880e182c83 (patch) | |
tree | 3f581eb831a6f7f16ab30bd0f8e8d80b5b97fe50 /net/dccp | |
parent | ea4f76ae13b4240dac304ed50636391d6b22e9c5 (diff) |
[TFRC]: Migrate TX history to singly-linked lis
This patch was based on another made by Gerrit Renker, his changelog was:
------------------------------------------------------
The patch set migrates TFRC TX history to a singly-linked list.
The details are:
* use of a consistent naming scheme (all TFRC functions now begin with `tfrc_');
* allocation and cleanup are taken care of internally;
* provision of a lookup function, which is used by the CCID TX infrastructure
to determine the time a packet was sent (in turn used for RTT sampling);
* integration of the new interface with the present use in CCID3.
------------------------------------------------------
Simplifications I did:
. removing the tfrc_tx_hist_head that had a pointer to the list head and
another for the slabcache.
. No need for creating a slabcache for each CCID that wants to use the TFRC
tx history routines, create a single slabcache when the dccp_tfrc_lib module
init routine is called.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 57 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 3 | ||||
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.c | 12 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 138 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.h | 79 |
5 files changed, 102 insertions, 187 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 42893b1dfa09..f73542ab9d08 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -49,7 +49,6 @@ static int ccid3_debug; | |||
49 | #define ccid3_pr_debug(format, a...) | 49 | #define ccid3_pr_debug(format, a...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | static struct dccp_tx_hist *ccid3_tx_hist; | ||
53 | static struct dccp_rx_hist *ccid3_rx_hist; | 52 | static struct dccp_rx_hist *ccid3_rx_hist; |
54 | 53 | ||
55 | /* | 54 | /* |
@@ -389,28 +388,18 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, | |||
389 | unsigned int len) | 388 | unsigned int len) |
390 | { | 389 | { |
391 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 390 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
392 | struct dccp_tx_hist_entry *packet; | ||
393 | 391 | ||
394 | ccid3_hc_tx_update_s(hctx, len); | 392 | ccid3_hc_tx_update_s(hctx, len); |
395 | 393 | ||
396 | packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC); | 394 | if (tfrc_tx_hist_add(&hctx->ccid3hctx_hist, dccp_sk(sk)->dccps_gss)) |
397 | if (unlikely(packet == NULL)) { | ||
398 | DCCP_CRIT("packet history - out of memory!"); | 395 | DCCP_CRIT("packet history - out of memory!"); |
399 | return; | ||
400 | } | ||
401 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet); | ||
402 | |||
403 | packet->dccphtx_tstamp = ktime_get_real(); | ||
404 | packet->dccphtx_seqno = dccp_sk(sk)->dccps_gss; | ||
405 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | ||
406 | packet->dccphtx_sent = 1; | ||
407 | } | 396 | } |
408 | 397 | ||
409 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 398 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
410 | { | 399 | { |
411 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 400 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
412 | struct ccid3_options_received *opt_recv; | 401 | struct ccid3_options_received *opt_recv; |
413 | struct dccp_tx_hist_entry *packet; | 402 | struct tfrc_tx_hist_entry *packet; |
414 | ktime_t now; | 403 | ktime_t now; |
415 | unsigned long t_nfb; | 404 | unsigned long t_nfb; |
416 | u32 pinv, r_sample; | 405 | u32 pinv, r_sample; |
@@ -425,16 +414,19 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
425 | switch (hctx->ccid3hctx_state) { | 414 | switch (hctx->ccid3hctx_state) { |
426 | case TFRC_SSTATE_NO_FBACK: | 415 | case TFRC_SSTATE_NO_FBACK: |
427 | case TFRC_SSTATE_FBACK: | 416 | case TFRC_SSTATE_FBACK: |
428 | /* get packet from history to look up t_recvdata */ | 417 | /* estimate RTT from history if ACK number is valid */ |
429 | packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, | 418 | packet = tfrc_tx_hist_find_entry(hctx->ccid3hctx_hist, |
430 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 419 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
431 | if (unlikely(packet == NULL)) { | 420 | if (packet == NULL) { |
432 | DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist " | 421 | DCCP_WARN("%s(%p): %s with bogus ACK-%llu\n", dccp_role(sk), sk, |
433 | "in history!\n", dccp_role(sk), sk, | 422 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type), |
434 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 423 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq); |
435 | dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); | ||
436 | return; | 424 | return; |
437 | } | 425 | } |
426 | /* | ||
427 | * Garbage-collect older (irrelevant) entries | ||
428 | */ | ||
429 | tfrc_tx_hist_purge(&packet->next); | ||
438 | 430 | ||
439 | /* Update receive rate in units of 64 * bytes/second */ | 431 | /* Update receive rate in units of 64 * bytes/second */ |
440 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; | 432 | hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate; |
@@ -451,7 +443,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
451 | /* | 443 | /* |
452 | * Calculate new RTT sample and update moving average | 444 | * Calculate new RTT sample and update moving average |
453 | */ | 445 | */ |
454 | r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, packet->dccphtx_tstamp)); | 446 | r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, packet->stamp)); |
455 | hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9); | 447 | hctx->ccid3hctx_rtt = tfrc_ewma(hctx->ccid3hctx_rtt, r_sample, 9); |
456 | 448 | ||
457 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { | 449 | if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { |
@@ -493,9 +485,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
493 | /* unschedule no feedback timer */ | 485 | /* unschedule no feedback timer */ |
494 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); | 486 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); |
495 | 487 | ||
496 | /* remove all packets older than the one acked from history */ | ||
497 | dccp_tx_hist_purge_older(ccid3_tx_hist, | ||
498 | &hctx->ccid3hctx_hist, packet); | ||
499 | /* | 488 | /* |
500 | * As we have calculated new ipi, delta, t_nom it is possible | 489 | * As we have calculated new ipi, delta, t_nom it is possible |
501 | * that we now can send a packet, so wake up dccp_wait_for_ccid | 490 | * that we now can send a packet, so wake up dccp_wait_for_ccid |
@@ -598,7 +587,7 @@ static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
598 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); | 587 | struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); |
599 | 588 | ||
600 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; | 589 | hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; |
601 | INIT_LIST_HEAD(&hctx->ccid3hctx_hist); | 590 | hctx->ccid3hctx_hist = NULL; |
602 | setup_timer(&hctx->ccid3hctx_no_feedback_timer, | 591 | setup_timer(&hctx->ccid3hctx_no_feedback_timer, |
603 | ccid3_hc_tx_no_feedback_timer, (unsigned long)sk); | 592 | ccid3_hc_tx_no_feedback_timer, (unsigned long)sk); |
604 | 593 | ||
@@ -612,8 +601,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) | |||
612 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); | 601 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); |
613 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); | 602 | sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); |
614 | 603 | ||
615 | /* Empty packet history */ | 604 | tfrc_tx_hist_purge(&hctx->ccid3hctx_hist); |
616 | dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); | ||
617 | } | 605 | } |
618 | 606 | ||
619 | static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) | 607 | static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) |
@@ -1036,19 +1024,12 @@ static __init int ccid3_module_init(void) | |||
1036 | if (ccid3_rx_hist == NULL) | 1024 | if (ccid3_rx_hist == NULL) |
1037 | goto out; | 1025 | goto out; |
1038 | 1026 | ||
1039 | ccid3_tx_hist = dccp_tx_hist_new("ccid3"); | ||
1040 | if (ccid3_tx_hist == NULL) | ||
1041 | goto out_free_rx; | ||
1042 | |||
1043 | rc = ccid_register(&ccid3); | 1027 | rc = ccid_register(&ccid3); |
1044 | if (rc != 0) | 1028 | if (rc != 0) |
1045 | goto out_free_tx; | 1029 | goto out_free_rx; |
1046 | out: | 1030 | out: |
1047 | return rc; | 1031 | return rc; |
1048 | 1032 | ||
1049 | out_free_tx: | ||
1050 | dccp_tx_hist_delete(ccid3_tx_hist); | ||
1051 | ccid3_tx_hist = NULL; | ||
1052 | out_free_rx: | 1033 | out_free_rx: |
1053 | dccp_rx_hist_delete(ccid3_rx_hist); | 1034 | dccp_rx_hist_delete(ccid3_rx_hist); |
1054 | ccid3_rx_hist = NULL; | 1035 | ccid3_rx_hist = NULL; |
@@ -1060,10 +1041,6 @@ static __exit void ccid3_module_exit(void) | |||
1060 | { | 1041 | { |
1061 | ccid_unregister(&ccid3); | 1042 | ccid_unregister(&ccid3); |
1062 | 1043 | ||
1063 | if (ccid3_tx_hist != NULL) { | ||
1064 | dccp_tx_hist_delete(ccid3_tx_hist); | ||
1065 | ccid3_tx_hist = NULL; | ||
1066 | } | ||
1067 | if (ccid3_rx_hist != NULL) { | 1044 | if (ccid3_rx_hist != NULL) { |
1068 | dccp_rx_hist_delete(ccid3_rx_hist); | 1045 | dccp_rx_hist_delete(ccid3_rx_hist); |
1069 | ccid3_rx_hist = NULL; | 1046 | ccid3_rx_hist = NULL; |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 36eca34228f0..b842a7dd99de 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/list.h> | 40 | #include <linux/list.h> |
41 | #include <linux/types.h> | 41 | #include <linux/types.h> |
42 | #include <linux/tfrc.h> | 42 | #include <linux/tfrc.h> |
43 | #include "lib/packet_history.h" | ||
43 | #include "../ccid.h" | 44 | #include "../ccid.h" |
44 | 45 | ||
45 | /* Two seconds as per RFC 3448 4.2 */ | 46 | /* Two seconds as per RFC 3448 4.2 */ |
@@ -111,7 +112,7 @@ struct ccid3_hc_tx_sock { | |||
111 | ktime_t ccid3hctx_t_ld; | 112 | ktime_t ccid3hctx_t_ld; |
112 | ktime_t ccid3hctx_t_nom; | 113 | ktime_t ccid3hctx_t_nom; |
113 | u32 ccid3hctx_delta; | 114 | u32 ccid3hctx_delta; |
114 | struct list_head ccid3hctx_hist; | 115 | struct tfrc_tx_hist_entry *ccid3hctx_hist; |
115 | struct ccid3_options_received ccid3hctx_options_received; | 116 | struct ccid3_options_received ccid3hctx_options_received; |
116 | }; | 117 | }; |
117 | 118 | ||
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index d26b88dbbb45..f2ca4eb74ddb 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c | |||
@@ -277,7 +277,7 @@ void dccp_li_update_li(struct sock *sk, | |||
277 | 277 | ||
278 | EXPORT_SYMBOL_GPL(dccp_li_update_li); | 278 | EXPORT_SYMBOL_GPL(dccp_li_update_li); |
279 | 279 | ||
280 | static __init int dccp_li_init(void) | 280 | int __init dccp_li_init(void) |
281 | { | 281 | { |
282 | dccp_li_cachep = kmem_cache_create("dccp_li_hist", | 282 | dccp_li_cachep = kmem_cache_create("dccp_li_hist", |
283 | sizeof(struct dccp_li_hist_entry), | 283 | sizeof(struct dccp_li_hist_entry), |
@@ -285,10 +285,10 @@ static __init int dccp_li_init(void) | |||
285 | return dccp_li_cachep == NULL ? -ENOBUFS : 0; | 285 | return dccp_li_cachep == NULL ? -ENOBUFS : 0; |
286 | } | 286 | } |
287 | 287 | ||
288 | static __exit void dccp_li_exit(void) | 288 | void dccp_li_exit(void) |
289 | { | 289 | { |
290 | kmem_cache_destroy(dccp_li_cachep); | 290 | if (dccp_li_cachep != NULL) { |
291 | kmem_cache_destroy(dccp_li_cachep); | ||
292 | dccp_li_cachep = NULL; | ||
293 | } | ||
291 | } | 294 | } |
292 | |||
293 | module_init(dccp_li_init); | ||
294 | module_exit(dccp_li_exit); | ||
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index 34c4f6047724..139736064713 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/packet_history.c | 2 | * net/dccp/packet_history.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2007 The University of Aberdeen, Scotland, UK |
5 | * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. | ||
5 | * | 6 | * |
6 | * An implementation of the DCCP protocol | 7 | * An implementation of the DCCP protocol |
7 | * | 8 | * |
@@ -39,93 +40,48 @@ | |||
39 | #include "packet_history.h" | 40 | #include "packet_history.h" |
40 | 41 | ||
41 | /* | 42 | /* |
42 | * Transmitter History Routines | 43 | * Transmitter History Routines |
43 | */ | 44 | */ |
44 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | 45 | static struct kmem_cache *tfrc_tx_hist; |
45 | { | ||
46 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | ||
47 | static const char dccp_tx_hist_mask[] = "tx_hist_%s"; | ||
48 | char *slab_name; | ||
49 | 46 | ||
50 | if (hist == NULL) | 47 | struct tfrc_tx_hist_entry * |
51 | goto out; | 48 | tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno) |
52 | |||
53 | slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1, | ||
54 | GFP_ATOMIC); | ||
55 | if (slab_name == NULL) | ||
56 | goto out_free_hist; | ||
57 | |||
58 | sprintf(slab_name, dccp_tx_hist_mask, name); | ||
59 | hist->dccptxh_slab = kmem_cache_create(slab_name, | ||
60 | sizeof(struct dccp_tx_hist_entry), | ||
61 | 0, SLAB_HWCACHE_ALIGN, | ||
62 | NULL); | ||
63 | if (hist->dccptxh_slab == NULL) | ||
64 | goto out_free_slab_name; | ||
65 | out: | ||
66 | return hist; | ||
67 | out_free_slab_name: | ||
68 | kfree(slab_name); | ||
69 | out_free_hist: | ||
70 | kfree(hist); | ||
71 | hist = NULL; | ||
72 | goto out; | ||
73 | } | ||
74 | |||
75 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
76 | |||
77 | void dccp_tx_hist_delete(struct dccp_tx_hist *hist) | ||
78 | { | 49 | { |
79 | const char* name = kmem_cache_name(hist->dccptxh_slab); | 50 | while (head != NULL && head->seqno != seqno) |
51 | head = head->next; | ||
80 | 52 | ||
81 | kmem_cache_destroy(hist->dccptxh_slab); | 53 | return head; |
82 | kfree(name); | ||
83 | kfree(hist); | ||
84 | } | 54 | } |
55 | EXPORT_SYMBOL_GPL(tfrc_tx_hist_find_entry); | ||
85 | 56 | ||
86 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | 57 | int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno) |
87 | |||
88 | struct dccp_tx_hist_entry * | ||
89 | dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) | ||
90 | { | 58 | { |
91 | struct dccp_tx_hist_entry *packet = NULL, *entry; | 59 | struct tfrc_tx_hist_entry *entry = kmem_cache_alloc(tfrc_tx_hist, gfp_any()); |
92 | 60 | ||
93 | list_for_each_entry(entry, list, dccphtx_node) | 61 | if (entry == NULL) |
94 | if (entry->dccphtx_seqno == seq) { | 62 | return -ENOBUFS; |
95 | packet = entry; | 63 | entry->seqno = seqno; |
96 | break; | 64 | entry->stamp = ktime_get_real(); |
97 | } | 65 | entry->next = *headp; |
98 | 66 | *headp = entry; | |
99 | return packet; | 67 | return 0; |
100 | } | 68 | } |
69 | EXPORT_SYMBOL_GPL(tfrc_tx_hist_add); | ||
101 | 70 | ||
102 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | 71 | void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp) |
103 | |||
104 | void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | ||
105 | { | 72 | { |
106 | struct dccp_tx_hist_entry *entry, *next; | 73 | struct tfrc_tx_hist_entry *head = *headp; |
107 | 74 | ||
108 | list_for_each_entry_safe(entry, next, list, dccphtx_node) { | 75 | while (head != NULL) { |
109 | list_del_init(&entry->dccphtx_node); | 76 | struct tfrc_tx_hist_entry *next = head->next; |
110 | dccp_tx_hist_entry_delete(hist, entry); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | ||
115 | 77 | ||
116 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | 78 | kmem_cache_free(tfrc_tx_hist, head); |
117 | struct list_head *list, | 79 | head = next; |
118 | struct dccp_tx_hist_entry *packet) | ||
119 | { | ||
120 | struct dccp_tx_hist_entry *next; | ||
121 | |||
122 | list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) { | ||
123 | list_del_init(&packet->dccphtx_node); | ||
124 | dccp_tx_hist_entry_delete(hist, packet); | ||
125 | } | 80 | } |
126 | } | ||
127 | 81 | ||
128 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | 82 | *headp = NULL; |
83 | } | ||
84 | EXPORT_SYMBOL_GPL(tfrc_tx_hist_purge); | ||
129 | 85 | ||
130 | /* | 86 | /* |
131 | * Receiver History Routines | 87 | * Receiver History Routines |
@@ -147,8 +103,7 @@ struct dccp_rx_hist *dccp_rx_hist_new(const char *name) | |||
147 | sprintf(slab_name, dccp_rx_hist_mask, name); | 103 | sprintf(slab_name, dccp_rx_hist_mask, name); |
148 | hist->dccprxh_slab = kmem_cache_create(slab_name, | 104 | hist->dccprxh_slab = kmem_cache_create(slab_name, |
149 | sizeof(struct dccp_rx_hist_entry), | 105 | sizeof(struct dccp_rx_hist_entry), |
150 | 0, SLAB_HWCACHE_ALIGN, | 106 | 0, SLAB_HWCACHE_ALIGN, NULL); |
151 | NULL); | ||
152 | if (hist->dccprxh_slab == NULL) | 107 | if (hist->dccprxh_slab == NULL) |
153 | goto out_free_slab_name; | 108 | goto out_free_slab_name; |
154 | out: | 109 | out: |
@@ -293,6 +248,37 @@ void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) | |||
293 | 248 | ||
294 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); | 249 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); |
295 | 250 | ||
251 | extern int __init dccp_li_init(void); | ||
252 | extern void dccp_li_exit(void); | ||
253 | |||
254 | static __init int packet_history_init(void) | ||
255 | { | ||
256 | if (dccp_li_init() != 0) | ||
257 | goto out; | ||
258 | |||
259 | tfrc_tx_hist = kmem_cache_create("tfrc_tx_hist", | ||
260 | sizeof(struct tfrc_tx_hist_entry), 0, | ||
261 | SLAB_HWCACHE_ALIGN, NULL); | ||
262 | if (tfrc_tx_hist == NULL) | ||
263 | goto out_li_exit; | ||
264 | |||
265 | return 0; | ||
266 | out_li_exit: | ||
267 | dccp_li_exit(); | ||
268 | out: | ||
269 | return -ENOBUFS; | ||
270 | } | ||
271 | module_init(packet_history_init); | ||
272 | |||
273 | static __exit void packet_history_exit(void) | ||
274 | { | ||
275 | if (tfrc_tx_hist != NULL) { | ||
276 | kmem_cache_destroy(tfrc_tx_hist); | ||
277 | tfrc_tx_hist = NULL; | ||
278 | } | ||
279 | dccp_li_exit(); | ||
280 | } | ||
281 | module_exit(packet_history_exit); | ||
296 | 282 | ||
297 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " | 283 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
298 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 284 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 032bb61c6e39..5c07182dd659 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h | |||
@@ -1,10 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/packet_history.h | 2 | * Packet RX/TX history data structures and routines for TFRC-based protocols. |
3 | * | 3 | * |
4 | * Copyright (c) 2007 The University of Aberdeen, Scotland, UK | ||
4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. | 5 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. |
5 | * | 6 | * |
6 | * An implementation of the DCCP protocol | ||
7 | * | ||
8 | * This code has been developed by the University of Waikato WAND | 7 | * This code has been developed by the University of Waikato WAND |
9 | * research group. For further information please see http://www.wand.net.nz/ | 8 | * research group. For further information please see http://www.wand.net.nz/ |
10 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz | 9 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz |
@@ -49,71 +48,23 @@ | |||
49 | #define TFRC_WIN_COUNT_PER_RTT 4 | 48 | #define TFRC_WIN_COUNT_PER_RTT 4 |
50 | #define TFRC_WIN_COUNT_LIMIT 16 | 49 | #define TFRC_WIN_COUNT_LIMIT 16 |
51 | 50 | ||
52 | /* | 51 | /** |
53 | * Transmitter History data structures and declarations | 52 | * tfrc_tx_hist_entry - Simple singly-linked TX history list |
53 | * @next: next oldest entry (LIFO order) | ||
54 | * @seqno: sequence number of this entry | ||
55 | * @stamp: send time of packet with sequence number @seqno | ||
54 | */ | 56 | */ |
55 | struct dccp_tx_hist_entry { | 57 | struct tfrc_tx_hist_entry { |
56 | struct list_head dccphtx_node; | 58 | struct tfrc_tx_hist_entry *next; |
57 | u64 dccphtx_seqno:48, | 59 | u64 seqno; |
58 | dccphtx_sent:1; | 60 | ktime_t stamp; |
59 | u32 dccphtx_rtt; | ||
60 | ktime_t dccphtx_tstamp; | ||
61 | }; | ||
62 | |||
63 | struct dccp_tx_hist { | ||
64 | struct kmem_cache *dccptxh_slab; | ||
65 | }; | 61 | }; |
66 | 62 | ||
67 | extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name); | 63 | extern int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno); |
68 | extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist); | 64 | extern void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp); |
69 | |||
70 | static inline struct dccp_tx_hist_entry * | ||
71 | dccp_tx_hist_entry_new(struct dccp_tx_hist *hist, | ||
72 | const gfp_t prio) | ||
73 | { | ||
74 | struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab, | ||
75 | prio); | ||
76 | |||
77 | if (entry != NULL) | ||
78 | entry->dccphtx_sent = 0; | ||
79 | |||
80 | return entry; | ||
81 | } | ||
82 | |||
83 | static inline struct dccp_tx_hist_entry * | ||
84 | dccp_tx_hist_head(struct list_head *list) | ||
85 | { | ||
86 | struct dccp_tx_hist_entry *head = NULL; | ||
87 | |||
88 | if (!list_empty(list)) | ||
89 | head = list_entry(list->next, struct dccp_tx_hist_entry, | ||
90 | dccphtx_node); | ||
91 | return head; | ||
92 | } | ||
93 | |||
94 | extern struct dccp_tx_hist_entry * | ||
95 | dccp_tx_hist_find_entry(const struct list_head *list, | ||
96 | const u64 seq); | ||
97 | |||
98 | static inline void dccp_tx_hist_add_entry(struct list_head *list, | ||
99 | struct dccp_tx_hist_entry *entry) | ||
100 | { | ||
101 | list_add(&entry->dccphtx_node, list); | ||
102 | } | ||
103 | |||
104 | static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist, | ||
105 | struct dccp_tx_hist_entry *entry) | ||
106 | { | ||
107 | if (entry != NULL) | ||
108 | kmem_cache_free(hist->dccptxh_slab, entry); | ||
109 | } | ||
110 | |||
111 | extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist, | ||
112 | struct list_head *list); | ||
113 | 65 | ||
114 | extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | 66 | extern struct tfrc_tx_hist_entry * |
115 | struct list_head *list, | 67 | tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 ackno); |
116 | struct dccp_tx_hist_entry *next); | ||
117 | 68 | ||
118 | /* | 69 | /* |
119 | * Receiver History data structures and declarations | 70 | * Receiver History data structures and declarations |