diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2009-01-05 00:42:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-05 00:42:53 -0500 |
commit | ddebc973c56b51b4e5d84d606f0430d81b895d67 (patch) | |
tree | cebe0e4461346072b2063132fc1d9cf8c3e148f1 /net | |
parent | 6ea2fde13abd3444008ab5e9585f9ed249e6047e (diff) |
dccp: Lockless integration of CCID congestion-control plugins
Based on Arnaldo's earlier patch, this patch integrates the standardised
CCID congestion control plugins (CCID-2 and CCID-3) of DCCP with dccp.ko:
* enables a faster connection path by eliminating the need to always go
through the CCID registration lock;
* updates the implementation to use only a single array whose size equals
the number of configured CCIDs instead of the maximum (256);
* since the CCIDs are now fixed array elements, synchronization is no
longer needed, simplifying use and implementation.
CCID-2 is suggested as minimum for a basic DCCP implementation (RFC 4340, 10);
CCID-3 is a standards-track CCID supported by RFC 4342 and RFC 5348.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/Kconfig | 4 | ||||
-rw-r--r-- | net/dccp/Makefile | 9 | ||||
-rw-r--r-- | net/dccp/ackvec.h | 4 | ||||
-rw-r--r-- | net/dccp/ccid.c | 156 | ||||
-rw-r--r-- | net/dccp/ccid.h | 11 | ||||
-rw-r--r-- | net/dccp/ccids/Kconfig | 70 | ||||
-rw-r--r-- | net/dccp/ccids/Makefile | 8 | ||||
-rw-r--r-- | net/dccp/ccids/ccid2.c | 22 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 23 | ||||
-rw-r--r-- | net/dccp/dccp.h | 2 | ||||
-rw-r--r-- | net/dccp/proto.c | 7 |
11 files changed, 148 insertions, 168 deletions
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig index 7aa2a7acc7ec..ad6dffd9070e 100644 --- a/net/dccp/Kconfig +++ b/net/dccp/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | menuconfig IP_DCCP | 1 | menuconfig IP_DCCP |
2 | tristate "The DCCP Protocol (EXPERIMENTAL)" | 2 | tristate "The DCCP Protocol (EXPERIMENTAL)" |
3 | depends on INET && EXPERIMENTAL | 3 | depends on INET && EXPERIMENTAL |
4 | select IP_DCCP_CCID2 | ||
5 | ---help--- | 4 | ---help--- |
6 | Datagram Congestion Control Protocol (RFC 4340) | 5 | Datagram Congestion Control Protocol (RFC 4340) |
7 | 6 | ||
@@ -25,9 +24,6 @@ config INET_DCCP_DIAG | |||
25 | def_tristate y if (IP_DCCP = y && INET_DIAG = y) | 24 | def_tristate y if (IP_DCCP = y && INET_DIAG = y) |
26 | def_tristate m | 25 | def_tristate m |
27 | 26 | ||
28 | config IP_DCCP_ACKVEC | ||
29 | bool | ||
30 | |||
31 | source "net/dccp/ccids/Kconfig" | 27 | source "net/dccp/ccids/Kconfig" |
32 | 28 | ||
33 | menu "DCCP Kernel Hacking" | 29 | menu "DCCP Kernel Hacking" |
diff --git a/net/dccp/Makefile b/net/dccp/Makefile index f4f8793aafff..5ff2e7b35690 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile | |||
@@ -2,14 +2,19 @@ obj-$(CONFIG_IP_DCCP) += dccp.o dccp_ipv4.o | |||
2 | 2 | ||
3 | dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o | 3 | dccp-y := ccid.o feat.o input.o minisocks.o options.o output.o proto.o timer.o |
4 | 4 | ||
5 | # | ||
6 | # CCID algorithms to be used by dccp.ko | ||
7 | # | ||
8 | # CCID-2 is default (RFC 4340, p. 77) and has Ack Vectors as dependency | ||
9 | dccp-y += ccids/ccid2.o ackvec.o | ||
10 | dccp-$(CONFIG_IP_DCCP_CCID3) += ccids/ccid3.o | ||
11 | |||
5 | dccp_ipv4-y := ipv4.o | 12 | dccp_ipv4-y := ipv4.o |
6 | 13 | ||
7 | # build dccp_ipv6 as module whenever either IPv6 or DCCP is a module | 14 | # build dccp_ipv6 as module whenever either IPv6 or DCCP is a module |
8 | obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o | 15 | obj-$(subst y,$(CONFIG_IP_DCCP),$(CONFIG_IPV6)) += dccp_ipv6.o |
9 | dccp_ipv6-y := ipv6.o | 16 | dccp_ipv6-y := ipv6.o |
10 | 17 | ||
11 | dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o | ||
12 | |||
13 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o | 18 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o |
14 | obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o | 19 | obj-$(CONFIG_NET_DCCPPROBE) += dccp_probe.o |
15 | 20 | ||
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h index 4ccee030524e..569a33a79baa 100644 --- a/net/dccp/ackvec.h +++ b/net/dccp/ackvec.h | |||
@@ -84,7 +84,7 @@ struct dccp_ackvec_record { | |||
84 | struct sock; | 84 | struct sock; |
85 | struct sk_buff; | 85 | struct sk_buff; |
86 | 86 | ||
87 | #ifdef CONFIG_IP_DCCP_ACKVEC | 87 | #ifndef ___OLD_INTERFACE_TO_BE_REMOVED___ |
88 | extern int dccp_ackvec_init(void); | 88 | extern int dccp_ackvec_init(void); |
89 | extern void dccp_ackvec_exit(void); | 89 | extern void dccp_ackvec_exit(void); |
90 | 90 | ||
@@ -106,7 +106,7 @@ static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) | |||
106 | { | 106 | { |
107 | return av->av_vec_len; | 107 | return av->av_vec_len; |
108 | } | 108 | } |
109 | #else /* CONFIG_IP_DCCP_ACKVEC */ | 109 | #else /* ___OLD_INTERFACE_TO_BE_REMOVED___ */ |
110 | static inline int dccp_ackvec_init(void) | 110 | static inline int dccp_ackvec_init(void) |
111 | { | 111 | { |
112 | return 0; | 112 | return 0; |
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c index bcc643f992ae..538d3b1da623 100644 --- a/net/dccp/ccid.c +++ b/net/dccp/ccid.c | |||
@@ -13,6 +13,70 @@ | |||
13 | 13 | ||
14 | #include "ccid.h" | 14 | #include "ccid.h" |
15 | 15 | ||
16 | static struct ccid_operations *ccids[] = { | ||
17 | &ccid2_ops, | ||
18 | #ifdef CONFIG_IP_DCCP_CCID3 | ||
19 | &ccid3_ops, | ||
20 | #endif | ||
21 | }; | ||
22 | |||
23 | static struct ccid_operations *ccid_by_number(const u8 id) | ||
24 | { | ||
25 | int i; | ||
26 | |||
27 | for (i = 0; i < ARRAY_SIZE(ccids); i++) | ||
28 | if (ccids[i]->ccid_id == id) | ||
29 | return ccids[i]; | ||
30 | return NULL; | ||
31 | } | ||
32 | |||
33 | /* check that up to @array_len members in @ccid_array are supported */ | ||
34 | bool ccid_support_check(u8 const *ccid_array, u8 array_len) | ||
35 | { | ||
36 | while (array_len > 0) | ||
37 | if (ccid_by_number(ccid_array[--array_len]) == NULL) | ||
38 | return false; | ||
39 | return true; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * ccid_get_builtin_ccids - Populate a list of built-in CCIDs | ||
44 | * @ccid_array: pointer to copy into | ||
45 | * @array_len: value to return length into | ||
46 | * This function allocates memory - caller must see that it is freed after use. | ||
47 | */ | ||
48 | int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len) | ||
49 | { | ||
50 | *ccid_array = kmalloc(ARRAY_SIZE(ccids), gfp_any()); | ||
51 | if (*ccid_array == NULL) | ||
52 | return -ENOBUFS; | ||
53 | |||
54 | for (*array_len = 0; *array_len < ARRAY_SIZE(ccids); *array_len += 1) | ||
55 | (*ccid_array)[*array_len] = ccids[*array_len]->ccid_id; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int ccid_getsockopt_builtin_ccids(struct sock *sk, int len, | ||
60 | char __user *optval, int __user *optlen) | ||
61 | { | ||
62 | u8 *ccid_array, array_len; | ||
63 | int err = 0; | ||
64 | |||
65 | if (len < ARRAY_SIZE(ccids)) | ||
66 | return -EINVAL; | ||
67 | |||
68 | if (ccid_get_builtin_ccids(&ccid_array, &array_len)) | ||
69 | return -ENOBUFS; | ||
70 | |||
71 | if (put_user(array_len, optlen) || | ||
72 | copy_to_user(optval, ccid_array, array_len)) | ||
73 | err = -EFAULT; | ||
74 | |||
75 | kfree(ccid_array); | ||
76 | return err; | ||
77 | } | ||
78 | |||
79 | #ifdef ___OLD_INTERFACE_TO_BE_REMOVED___ | ||
16 | static u8 builtin_ccids[] = { | 80 | static u8 builtin_ccids[] = { |
17 | DCCPC_CCID2, /* CCID2 is supported by default */ | 81 | DCCPC_CCID2, /* CCID2 is supported by default */ |
18 | #if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) | 82 | #if defined(CONFIG_IP_DCCP_CCID3) || defined(CONFIG_IP_DCCP_CCID3_MODULE) |
@@ -62,6 +126,7 @@ static inline void ccids_read_unlock(void) | |||
62 | #define ccids_read_lock() do { } while(0) | 126 | #define ccids_read_lock() do { } while(0) |
63 | #define ccids_read_unlock() do { } while(0) | 127 | #define ccids_read_unlock() do { } while(0) |
64 | #endif | 128 | #endif |
129 | #endif /* ___OLD_INTERFACE_TO_BE_REMOVED___ */ | ||
65 | 130 | ||
66 | static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...) | 131 | static struct kmem_cache *ccid_kmem_cache_create(int obj_size, const char *fmt,...) |
67 | { | 132 | { |
@@ -93,6 +158,7 @@ static void ccid_kmem_cache_destroy(struct kmem_cache *slab) | |||
93 | } | 158 | } |
94 | } | 159 | } |
95 | 160 | ||
161 | #ifdef ___OLD_INTERFACE_TO_BE_REMOVED___ | ||
96 | /* check that up to @array_len members in @ccid_array are supported */ | 162 | /* check that up to @array_len members in @ccid_array are supported */ |
97 | bool ccid_support_check(u8 const *ccid_array, u8 array_len) | 163 | bool ccid_support_check(u8 const *ccid_array, u8 array_len) |
98 | { | 164 | { |
@@ -133,8 +199,9 @@ int ccid_getsockopt_builtin_ccids(struct sock *sk, int len, | |||
133 | return -EFAULT; | 199 | return -EFAULT; |
134 | return 0; | 200 | return 0; |
135 | } | 201 | } |
202 | #endif /* ___OLD_INTERFACE_TO_BE_REMOVED___ */ | ||
136 | 203 | ||
137 | int ccid_register(struct ccid_operations *ccid_ops) | 204 | static int ccid_activate(struct ccid_operations *ccid_ops) |
138 | { | 205 | { |
139 | int err = -ENOBUFS; | 206 | int err = -ENOBUFS; |
140 | 207 | ||
@@ -152,79 +219,40 @@ int ccid_register(struct ccid_operations *ccid_ops) | |||
152 | if (ccid_ops->ccid_hc_tx_slab == NULL) | 219 | if (ccid_ops->ccid_hc_tx_slab == NULL) |
153 | goto out_free_rx_slab; | 220 | goto out_free_rx_slab; |
154 | 221 | ||
155 | ccids_write_lock(); | 222 | pr_info("CCID: Activated CCID %d (%s)\n", |
156 | err = -EEXIST; | ||
157 | if (ccids[ccid_ops->ccid_id] == NULL) { | ||
158 | ccids[ccid_ops->ccid_id] = ccid_ops; | ||
159 | err = 0; | ||
160 | } | ||
161 | ccids_write_unlock(); | ||
162 | if (err != 0) | ||
163 | goto out_free_tx_slab; | ||
164 | |||
165 | pr_info("CCID: Registered CCID %d (%s)\n", | ||
166 | ccid_ops->ccid_id, ccid_ops->ccid_name); | 223 | ccid_ops->ccid_id, ccid_ops->ccid_name); |
224 | err = 0; | ||
167 | out: | 225 | out: |
168 | return err; | 226 | return err; |
169 | out_free_tx_slab: | ||
170 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); | ||
171 | ccid_ops->ccid_hc_tx_slab = NULL; | ||
172 | goto out; | ||
173 | out_free_rx_slab: | 227 | out_free_rx_slab: |
174 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); | 228 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); |
175 | ccid_ops->ccid_hc_rx_slab = NULL; | 229 | ccid_ops->ccid_hc_rx_slab = NULL; |
176 | goto out; | 230 | goto out; |
177 | } | 231 | } |
178 | 232 | ||
179 | EXPORT_SYMBOL_GPL(ccid_register); | 233 | static void ccid_deactivate(struct ccid_operations *ccid_ops) |
180 | |||
181 | int ccid_unregister(struct ccid_operations *ccid_ops) | ||
182 | { | 234 | { |
183 | ccids_write_lock(); | ||
184 | ccids[ccid_ops->ccid_id] = NULL; | ||
185 | ccids_write_unlock(); | ||
186 | |||
187 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); | 235 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab); |
188 | ccid_ops->ccid_hc_tx_slab = NULL; | 236 | ccid_ops->ccid_hc_tx_slab = NULL; |
189 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); | 237 | ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); |
190 | ccid_ops->ccid_hc_rx_slab = NULL; | 238 | ccid_ops->ccid_hc_rx_slab = NULL; |
191 | 239 | ||
192 | pr_info("CCID: Unregistered CCID %d (%s)\n", | 240 | pr_info("CCID: Deactivated CCID %d (%s)\n", |
193 | ccid_ops->ccid_id, ccid_ops->ccid_name); | 241 | ccid_ops->ccid_id, ccid_ops->ccid_name); |
194 | return 0; | ||
195 | } | 242 | } |
196 | 243 | ||
197 | EXPORT_SYMBOL_GPL(ccid_unregister); | ||
198 | |||
199 | struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) | 244 | struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) |
200 | { | 245 | { |
201 | struct ccid_operations *ccid_ops; | 246 | struct ccid_operations *ccid_ops = ccid_by_number(id); |
202 | struct ccid *ccid = NULL; | 247 | struct ccid *ccid = NULL; |
203 | 248 | ||
204 | ccids_read_lock(); | ||
205 | #ifdef CONFIG_MODULES | ||
206 | if (ccids[id] == NULL) { | ||
207 | /* We only try to load if in process context */ | ||
208 | ccids_read_unlock(); | ||
209 | if (gfp & GFP_ATOMIC) | ||
210 | goto out; | ||
211 | request_module("net-dccp-ccid-%d", id); | ||
212 | ccids_read_lock(); | ||
213 | } | ||
214 | #endif | ||
215 | ccid_ops = ccids[id]; | ||
216 | if (ccid_ops == NULL) | 249 | if (ccid_ops == NULL) |
217 | goto out_unlock; | 250 | goto out; |
218 | |||
219 | if (!try_module_get(ccid_ops->ccid_owner)) | ||
220 | goto out_unlock; | ||
221 | |||
222 | ccids_read_unlock(); | ||
223 | 251 | ||
224 | ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : | 252 | ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab : |
225 | ccid_ops->ccid_hc_tx_slab, gfp); | 253 | ccid_ops->ccid_hc_tx_slab, gfp); |
226 | if (ccid == NULL) | 254 | if (ccid == NULL) |
227 | goto out_module_put; | 255 | goto out; |
228 | ccid->ccid_ops = ccid_ops; | 256 | ccid->ccid_ops = ccid_ops; |
229 | if (rx) { | 257 | if (rx) { |
230 | memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size); | 258 | memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size); |
@@ -239,15 +267,10 @@ struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp) | |||
239 | } | 267 | } |
240 | out: | 268 | out: |
241 | return ccid; | 269 | return ccid; |
242 | out_unlock: | ||
243 | ccids_read_unlock(); | ||
244 | goto out; | ||
245 | out_free_ccid: | 270 | out_free_ccid: |
246 | kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab : | 271 | kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab : |
247 | ccid_ops->ccid_hc_tx_slab, ccid); | 272 | ccid_ops->ccid_hc_tx_slab, ccid); |
248 | ccid = NULL; | 273 | ccid = NULL; |
249 | out_module_put: | ||
250 | module_put(ccid_ops->ccid_owner); | ||
251 | goto out; | 274 | goto out; |
252 | } | 275 | } |
253 | 276 | ||
@@ -270,10 +293,6 @@ static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx) | |||
270 | ccid_ops->ccid_hc_tx_exit(sk); | 293 | ccid_ops->ccid_hc_tx_exit(sk); |
271 | kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid); | 294 | kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid); |
272 | } | 295 | } |
273 | ccids_read_lock(); | ||
274 | if (ccids[ccid_ops->ccid_id] != NULL) | ||
275 | module_put(ccid_ops->ccid_owner); | ||
276 | ccids_read_unlock(); | ||
277 | } | 296 | } |
278 | 297 | ||
279 | void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk) | 298 | void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk) |
@@ -289,3 +308,28 @@ void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk) | |||
289 | } | 308 | } |
290 | 309 | ||
291 | EXPORT_SYMBOL_GPL(ccid_hc_tx_delete); | 310 | EXPORT_SYMBOL_GPL(ccid_hc_tx_delete); |
311 | |||
312 | int __init ccid_initialize_builtins(void) | ||
313 | { | ||
314 | int i, err; | ||
315 | |||
316 | for (i = 0; i < ARRAY_SIZE(ccids); i++) { | ||
317 | err = ccid_activate(ccids[i]); | ||
318 | if (err) | ||
319 | goto unwind_registrations; | ||
320 | } | ||
321 | return 0; | ||
322 | |||
323 | unwind_registrations: | ||
324 | while(--i >= 0) | ||
325 | ccid_deactivate(ccids[i]); | ||
326 | return err; | ||
327 | } | ||
328 | |||
329 | void ccid_cleanup_builtins(void) | ||
330 | { | ||
331 | int i; | ||
332 | |||
333 | for (i = 0; i < ARRAY_SIZE(ccids); i++) | ||
334 | ccid_deactivate(ccids[i]); | ||
335 | } | ||
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 18f69423a708..75c21c52ed7a 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h | |||
@@ -29,7 +29,6 @@ struct tcp_info; | |||
29 | * @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.) | 29 | * @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.) |
30 | * @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled) | 30 | * @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled) |
31 | * @ccid_name: alphabetical identifier string for @ccid_id | 31 | * @ccid_name: alphabetical identifier string for @ccid_id |
32 | * @ccid_owner: module which implements/owns this CCID | ||
33 | * @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection | 32 | * @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection |
34 | * @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket | 33 | * @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket |
35 | * | 34 | * |
@@ -48,7 +47,6 @@ struct ccid_operations { | |||
48 | unsigned char ccid_id; | 47 | unsigned char ccid_id; |
49 | __u32 ccid_ccmps; | 48 | __u32 ccid_ccmps; |
50 | const char *ccid_name; | 49 | const char *ccid_name; |
51 | struct module *ccid_owner; | ||
52 | struct kmem_cache *ccid_hc_rx_slab, | 50 | struct kmem_cache *ccid_hc_rx_slab, |
53 | *ccid_hc_tx_slab; | 51 | *ccid_hc_tx_slab; |
54 | __u32 ccid_hc_rx_obj_size, | 52 | __u32 ccid_hc_rx_obj_size, |
@@ -90,8 +88,13 @@ struct ccid_operations { | |||
90 | int __user *optlen); | 88 | int __user *optlen); |
91 | }; | 89 | }; |
92 | 90 | ||
93 | extern int ccid_register(struct ccid_operations *ccid_ops); | 91 | extern struct ccid_operations ccid2_ops; |
94 | extern int ccid_unregister(struct ccid_operations *ccid_ops); | 92 | #ifdef CONFIG_IP_DCCP_CCID3 |
93 | extern struct ccid_operations ccid3_ops; | ||
94 | #endif | ||
95 | |||
96 | extern int ccid_initialize_builtins(void); | ||
97 | extern void ccid_cleanup_builtins(void); | ||
95 | 98 | ||
96 | struct ccid { | 99 | struct ccid { |
97 | struct ccid_operations *ccid_ops; | 100 | struct ccid_operations *ccid_ops; |
diff --git a/net/dccp/ccids/Kconfig b/net/dccp/ccids/Kconfig index 12275943eab8..b30f049cf1d3 100644 --- a/net/dccp/ccids/Kconfig +++ b/net/dccp/ccids/Kconfig | |||
@@ -1,80 +1,52 @@ | |||
1 | menu "DCCP CCIDs Configuration (EXPERIMENTAL)" | 1 | menu "DCCP CCIDs Configuration (EXPERIMENTAL)" |
2 | depends on EXPERIMENTAL | 2 | depends on EXPERIMENTAL |
3 | 3 | ||
4 | config IP_DCCP_CCID2 | ||
5 | tristate "CCID2 (TCP-Like) (EXPERIMENTAL)" | ||
6 | def_tristate IP_DCCP | ||
7 | select IP_DCCP_ACKVEC | ||
8 | ---help--- | ||
9 | CCID 2, TCP-like Congestion Control, denotes Additive Increase, | ||
10 | Multiplicative Decrease (AIMD) congestion control with behavior | ||
11 | modelled directly on TCP, including congestion window, slow start, | ||
12 | timeouts, and so forth [RFC 2581]. CCID 2 achieves maximum | ||
13 | bandwidth over the long term, consistent with the use of end-to-end | ||
14 | congestion control, but halves its congestion window in response to | ||
15 | each congestion event. This leads to the abrupt rate changes | ||
16 | typical of TCP. Applications should use CCID 2 if they prefer | ||
17 | maximum bandwidth utilization to steadiness of rate. This is often | ||
18 | the case for applications that are not playing their data directly | ||
19 | to the user. For example, a hypothetical application that | ||
20 | transferred files over DCCP, using application-level retransmissions | ||
21 | for lost packets, would prefer CCID 2 to CCID 3. On-line games may | ||
22 | also prefer CCID 2. See RFC 4341 for further details. | ||
23 | |||
24 | CCID2 is the default CCID used by DCCP. | ||
25 | |||
26 | config IP_DCCP_CCID2_DEBUG | 4 | config IP_DCCP_CCID2_DEBUG |
27 | bool "CCID2 debugging messages" | 5 | bool "CCID-2 debugging messages" |
28 | depends on IP_DCCP_CCID2 | 6 | ---help--- |
29 | ---help--- | 7 | Enable CCID-2 specific debugging messages. |
30 | Enable CCID2-specific debugging messages. | ||
31 | 8 | ||
32 | When compiling CCID2 as a module, this debugging output can | 9 | The debugging output can additionally be toggled by setting the |
33 | additionally be toggled by setting the ccid2_debug module | 10 | ccid2_debug parameter to 0 or 1. |
34 | parameter to 0 or 1. | ||
35 | 11 | ||
36 | If in doubt, say N. | 12 | If in doubt, say N. |
37 | 13 | ||
38 | config IP_DCCP_CCID3 | 14 | config IP_DCCP_CCID3 |
39 | tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)" | 15 | bool "CCID-3 (TCP-Friendly) (EXPERIMENTAL)" |
40 | def_tristate IP_DCCP | 16 | def_bool y if (IP_DCCP = y || IP_DCCP = m) |
41 | select IP_DCCP_TFRC_LIB | 17 | select IP_DCCP_TFRC_LIB |
42 | ---help--- | 18 | ---help--- |
43 | CCID 3 denotes TCP-Friendly Rate Control (TFRC), an equation-based | 19 | CCID-3 denotes TCP-Friendly Rate Control (TFRC), an equation-based |
44 | rate-controlled congestion control mechanism. TFRC is designed to | 20 | rate-controlled congestion control mechanism. TFRC is designed to |
45 | be reasonably fair when competing for bandwidth with TCP-like flows, | 21 | be reasonably fair when competing for bandwidth with TCP-like flows, |
46 | where a flow is "reasonably fair" if its sending rate is generally | 22 | where a flow is "reasonably fair" if its sending rate is generally |
47 | within a factor of two of the sending rate of a TCP flow under the | 23 | within a factor of two of the sending rate of a TCP flow under the |
48 | same conditions. However, TFRC has a much lower variation of | 24 | same conditions. However, TFRC has a much lower variation of |
49 | throughput over time compared with TCP, which makes CCID 3 more | 25 | throughput over time compared with TCP, which makes CCID-3 more |
50 | suitable than CCID 2 for applications such streaming media where a | 26 | suitable than CCID-2 for applications such streaming media where a |
51 | relatively smooth sending rate is of importance. | 27 | relatively smooth sending rate is of importance. |
52 | 28 | ||
53 | CCID 3 is further described in RFC 4342, | 29 | CCID-3 is further described in RFC 4342, |
54 | http://www.ietf.org/rfc/rfc4342.txt | 30 | http://www.ietf.org/rfc/rfc4342.txt |
55 | 31 | ||
56 | The TFRC congestion control algorithms were initially described in | 32 | The TFRC congestion control algorithms were initially described in |
57 | RFC 3448. | 33 | RFC 5448. |
58 | 34 | ||
59 | This text was extracted from RFC 4340 (sec. 10.2), | 35 | This text was extracted from RFC 4340 (sec. 10.2), |
60 | http://www.ietf.org/rfc/rfc4340.txt | 36 | http://www.ietf.org/rfc/rfc4340.txt |
61 | |||
62 | To compile this CCID as a module, choose M here: the module will be | ||
63 | called dccp_ccid3. | ||
64 | 37 | ||
65 | If in doubt, say M. | 38 | If in doubt, say N. |
66 | 39 | ||
67 | config IP_DCCP_CCID3_DEBUG | 40 | config IP_DCCP_CCID3_DEBUG |
68 | bool "CCID3 debugging messages" | 41 | bool "CCID-3 debugging messages" |
69 | depends on IP_DCCP_CCID3 | 42 | depends on IP_DCCP_CCID3 |
70 | ---help--- | 43 | ---help--- |
71 | Enable CCID3-specific debugging messages. | 44 | Enable CCID-3 specific debugging messages. |
72 | 45 | ||
73 | When compiling CCID3 as a module, this debugging output can | 46 | The debugging output can additionally be toggled by setting the |
74 | additionally be toggled by setting the ccid3_debug module | 47 | ccid3_debug parameter to 0 or 1. |
75 | parameter to 0 or 1. | ||
76 | 48 | ||
77 | If in doubt, say N. | 49 | If in doubt, say N. |
78 | 50 | ||
79 | config IP_DCCP_CCID3_RTO | 51 | config IP_DCCP_CCID3_RTO |
80 | int "Use higher bound for nofeedback timer" | 52 | int "Use higher bound for nofeedback timer" |
diff --git a/net/dccp/ccids/Makefile b/net/dccp/ccids/Makefile index 438f20bccff7..cdaefffbb777 100644 --- a/net/dccp/ccids/Makefile +++ b/net/dccp/ccids/Makefile | |||
@@ -1,9 +1 @@ | |||
1 | obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o | ||
2 | |||
3 | dccp_ccid3-y := ccid3.o | ||
4 | |||
5 | obj-$(CONFIG_IP_DCCP_CCID2) += dccp_ccid2.o | ||
6 | |||
7 | dccp_ccid2-y := ccid2.o | ||
8 | |||
9 | obj-y += lib/ | obj-y += lib/ | |
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index c9ea19a4d85e..d235294ace23 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -768,10 +768,9 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
768 | } | 768 | } |
769 | } | 769 | } |
770 | 770 | ||
771 | static struct ccid_operations ccid2 = { | 771 | struct ccid_operations ccid2_ops = { |
772 | .ccid_id = DCCPC_CCID2, | 772 | .ccid_id = DCCPC_CCID2, |
773 | .ccid_name = "TCP-like", | 773 | .ccid_name = "TCP-like", |
774 | .ccid_owner = THIS_MODULE, | ||
775 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), | 774 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), |
776 | .ccid_hc_tx_init = ccid2_hc_tx_init, | 775 | .ccid_hc_tx_init = ccid2_hc_tx_init, |
777 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, | 776 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, |
@@ -784,22 +783,5 @@ static struct ccid_operations ccid2 = { | |||
784 | 783 | ||
785 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG | 784 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
786 | module_param(ccid2_debug, bool, 0644); | 785 | module_param(ccid2_debug, bool, 0644); |
787 | MODULE_PARM_DESC(ccid2_debug, "Enable debug messages"); | 786 | MODULE_PARM_DESC(ccid2_debug, "Enable CCID-2 debug messages"); |
788 | #endif | 787 | #endif |
789 | |||
790 | static __init int ccid2_module_init(void) | ||
791 | { | ||
792 | return ccid_register(&ccid2); | ||
793 | } | ||
794 | module_init(ccid2_module_init); | ||
795 | |||
796 | static __exit void ccid2_module_exit(void) | ||
797 | { | ||
798 | ccid_unregister(&ccid2); | ||
799 | } | ||
800 | module_exit(ccid2_module_exit); | ||
801 | |||
802 | MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>"); | ||
803 | MODULE_DESCRIPTION("DCCP TCP-Like (CCID2) CCID"); | ||
804 | MODULE_LICENSE("GPL"); | ||
805 | MODULE_ALIAS("net-dccp-ccid-2"); | ||
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 3b8bd7ca6761..a27b7f4c19c5 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -940,10 +940,9 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, | |||
940 | return 0; | 940 | return 0; |
941 | } | 941 | } |
942 | 942 | ||
943 | static struct ccid_operations ccid3 = { | 943 | struct ccid_operations ccid3_ops = { |
944 | .ccid_id = DCCPC_CCID3, | 944 | .ccid_id = DCCPC_CCID3, |
945 | .ccid_name = "TCP-Friendly Rate Control", | 945 | .ccid_name = "TCP-Friendly Rate Control", |
946 | .ccid_owner = THIS_MODULE, | ||
947 | .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), | 946 | .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), |
948 | .ccid_hc_tx_init = ccid3_hc_tx_init, | 947 | .ccid_hc_tx_init = ccid3_hc_tx_init, |
949 | .ccid_hc_tx_exit = ccid3_hc_tx_exit, | 948 | .ccid_hc_tx_exit = ccid3_hc_tx_exit, |
@@ -964,23 +963,5 @@ static struct ccid_operations ccid3 = { | |||
964 | 963 | ||
965 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | 964 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
966 | module_param(ccid3_debug, bool, 0644); | 965 | module_param(ccid3_debug, bool, 0644); |
967 | MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); | 966 | MODULE_PARM_DESC(ccid3_debug, "Enable CCID-3 debug messages"); |
968 | #endif | 967 | #endif |
969 | |||
970 | static __init int ccid3_module_init(void) | ||
971 | { | ||
972 | return ccid_register(&ccid3); | ||
973 | } | ||
974 | module_init(ccid3_module_init); | ||
975 | |||
976 | static __exit void ccid3_module_exit(void) | ||
977 | { | ||
978 | ccid_unregister(&ccid3); | ||
979 | } | ||
980 | module_exit(ccid3_module_exit); | ||
981 | |||
982 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " | ||
983 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | ||
984 | MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); | ||
985 | MODULE_LICENSE("GPL"); | ||
986 | MODULE_ALIAS("net-dccp-ccid-3"); | ||
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 0bc4c9a02e19..f2230fc168e1 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -432,10 +432,8 @@ static inline int dccp_ack_pending(const struct sock *sk) | |||
432 | { | 432 | { |
433 | const struct dccp_sock *dp = dccp_sk(sk); | 433 | const struct dccp_sock *dp = dccp_sk(sk); |
434 | return dp->dccps_timestamp_echo != 0 || | 434 | return dp->dccps_timestamp_echo != 0 || |
435 | #ifdef CONFIG_IP_DCCP_ACKVEC | ||
436 | (dp->dccps_hc_rx_ackvec != NULL && | 435 | (dp->dccps_hc_rx_ackvec != NULL && |
437 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || | 436 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || |
438 | #endif | ||
439 | inet_csk_ack_scheduled(sk); | 437 | inet_csk_ack_scheduled(sk); |
440 | } | 438 | } |
441 | 439 | ||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1747ccae8e8d..945b4d5d23b3 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -1118,9 +1118,15 @@ static int __init dccp_init(void) | |||
1118 | if (rc) | 1118 | if (rc) |
1119 | goto out_ackvec_exit; | 1119 | goto out_ackvec_exit; |
1120 | 1120 | ||
1121 | rc = ccid_initialize_builtins(); | ||
1122 | if (rc) | ||
1123 | goto out_sysctl_exit; | ||
1124 | |||
1121 | dccp_timestamping_init(); | 1125 | dccp_timestamping_init(); |
1122 | out: | 1126 | out: |
1123 | return rc; | 1127 | return rc; |
1128 | out_sysctl_exit: | ||
1129 | dccp_sysctl_exit(); | ||
1124 | out_ackvec_exit: | 1130 | out_ackvec_exit: |
1125 | dccp_ackvec_exit(); | 1131 | dccp_ackvec_exit(); |
1126 | out_free_dccp_mib: | 1132 | out_free_dccp_mib: |
@@ -1143,6 +1149,7 @@ out_free_percpu: | |||
1143 | 1149 | ||
1144 | static void __exit dccp_fini(void) | 1150 | static void __exit dccp_fini(void) |
1145 | { | 1151 | { |
1152 | ccid_cleanup_builtins(); | ||
1146 | dccp_mib_exit(); | 1153 | dccp_mib_exit(); |
1147 | free_pages((unsigned long)dccp_hashinfo.bhash, | 1154 | free_pages((unsigned long)dccp_hashinfo.bhash, |
1148 | get_order(dccp_hashinfo.bhash_size * | 1155 | get_order(dccp_hashinfo.bhash_size * |