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/ccids/lib | |
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/ccids/lib')
-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 |
3 files changed, 83 insertions, 146 deletions
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 |