Commit 91f0ebf7b6d5cb2b6e818d48587566144821babe

Authored by Arnaldo Carvalho de Melo
Committed by David S. Miller
1 parent f38c39d6ce

[DCCP] CCID: Improve CCID infrastructure

1. No need for ->ccid_init nor ->ccid_exit, this is what module_{init,exit}
   does and anynways neither ccid2 nor ccid3 were using it.

2. Rename struct ccid to struct ccid_operations and introduce struct ccid
   with a pointer to ccid_operations and rigth after it the rx or tx
   private state.

3. Remove the pointer to the state of the half connections from struct
   dccp_sock, now its derived thru ccid_priv() from the ccid pointer.

Now we also can implement the setsockopt for changing the CCID easily as
no ccid init routines can affect struct dccp_sock in any way that prevents
other CCIDs from working if a CCID switch operation is asked by apps.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 10 changed files with 260 additions and 212 deletions Side-by-side Diff

include/linux/dccp.h
... ... @@ -478,8 +478,6 @@
478 478 __u32 dccps_mss_cache;
479 479 struct dccp_options dccps_options;
480 480 struct dccp_ackvec *dccps_hc_rx_ackvec;
481   - void *dccps_hc_rx_ccid_private;
482   - void *dccps_hc_tx_ccid_private;
483 481 struct ccid *dccps_hc_rx_ccid;
484 482 struct ccid *dccps_hc_tx_ccid;
485 483 struct dccp_options_received dccps_options_received;
... ... @@ -13,7 +13,7 @@
13 13  
14 14 #include "ccid.h"
15 15  
16   -static struct ccid *ccids[CCID_MAX];
  16 +static struct ccid_operations *ccids[CCID_MAX];
17 17 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
18 18 static atomic_t ccids_lockct = ATOMIC_INIT(0);
19 19 static DEFINE_SPINLOCK(ccids_lock);
20 20  
21 21  
22 22  
23 23  
24 24  
25 25  
26 26  
27 27  
28 28  
29 29  
30 30  
31 31  
32 32  
33 33  
34 34  
35 35  
36 36  
37 37  
38 38  
39 39  
40 40  
41 41  
42 42  
43 43  
44 44  
45 45  
46 46  
47 47  
48 48  
49 49  
... ... @@ -55,83 +55,203 @@
55 55 #define ccids_read_unlock() do { } while(0)
56 56 #endif
57 57  
58   -int ccid_register(struct ccid *ccid)
  58 +static kmem_cache_t *ccid_kmem_cache_create(int obj_size, const char *fmt,...)
59 59 {
60   - int err;
  60 + kmem_cache_t *slab;
  61 + char slab_name_fmt[32], *slab_name;
  62 + va_list args;
61 63  
  64 + va_start(args, fmt);
  65 + vsnprintf(slab_name_fmt, sizeof(slab_name_fmt), fmt, args);
  66 + va_end(args);
  67 +
  68 + slab_name = kstrdup(slab_name_fmt, GFP_KERNEL);
  69 + if (slab_name == NULL)
  70 + return NULL;
  71 + slab = kmem_cache_create(slab_name, sizeof(struct ccid) + obj_size, 0,
  72 + SLAB_HWCACHE_ALIGN, NULL, NULL);
  73 + if (slab == NULL)
  74 + kfree(slab_name);
  75 + return slab;
  76 +}
  77 +
  78 +static void ccid_kmem_cache_destroy(kmem_cache_t *slab)
  79 +{
  80 + if (slab != NULL) {
  81 + const char *name = kmem_cache_name(slab);
  82 +
  83 + kmem_cache_destroy(slab);
  84 + kfree(name);
  85 + }
  86 +}
  87 +
  88 +int ccid_register(struct ccid_operations *ccid_ops)
  89 +{
  90 + int err = -ENOBUFS;
  91 +
  92 + ccid_ops->ccid_hc_rx_slab =
  93 + ccid_kmem_cache_create(ccid_ops->ccid_hc_rx_obj_size,
  94 + "%s_hc_rx_sock",
  95 + ccid_ops->ccid_name);
  96 + if (ccid_ops->ccid_hc_rx_slab == NULL)
  97 + goto out;
  98 +
  99 + ccid_ops->ccid_hc_tx_slab =
  100 + ccid_kmem_cache_create(ccid_ops->ccid_hc_tx_obj_size,
  101 + "%s_hc_tx_sock",
  102 + ccid_ops->ccid_name);
  103 + if (ccid_ops->ccid_hc_tx_slab == NULL)
  104 + goto out_free_rx_slab;
  105 +
62 106 ccids_write_lock();
63 107 err = -EEXIST;
64   - if (ccids[ccid->ccid_id] == NULL) {
65   - ccids[ccid->ccid_id] = ccid;
  108 + if (ccids[ccid_ops->ccid_id] == NULL) {
  109 + ccids[ccid_ops->ccid_id] = ccid_ops;
66 110 err = 0;
67 111 }
68 112 ccids_write_unlock();
69   - if (err == 0)
70   - pr_info("CCID: Registered CCID %d (%s)\n",
71   - ccid->ccid_id, ccid->ccid_name);
  113 + if (err != 0)
  114 + goto out_free_tx_slab;
  115 +
  116 + pr_info("CCID: Registered CCID %d (%s)\n",
  117 + ccid_ops->ccid_id, ccid_ops->ccid_name);
  118 +out:
72 119 return err;
  120 +out_free_tx_slab:
  121 + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
  122 + ccid_ops->ccid_hc_tx_slab = NULL;
  123 + goto out;
  124 +out_free_rx_slab:
  125 + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
  126 + ccid_ops->ccid_hc_rx_slab = NULL;
  127 + goto out;
73 128 }
74 129  
75 130 EXPORT_SYMBOL_GPL(ccid_register);
76 131  
77   -int ccid_unregister(struct ccid *ccid)
  132 +int ccid_unregister(struct ccid_operations *ccid_ops)
78 133 {
79 134 ccids_write_lock();
80   - ccids[ccid->ccid_id] = NULL;
  135 + ccids[ccid_ops->ccid_id] = NULL;
81 136 ccids_write_unlock();
  137 +
  138 + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_tx_slab);
  139 + ccid_ops->ccid_hc_tx_slab = NULL;
  140 + ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
  141 + ccid_ops->ccid_hc_rx_slab = NULL;
  142 +
82 143 pr_info("CCID: Unregistered CCID %d (%s)\n",
83   - ccid->ccid_id, ccid->ccid_name);
  144 + ccid_ops->ccid_id, ccid_ops->ccid_name);
84 145 return 0;
85 146 }
86 147  
87 148 EXPORT_SYMBOL_GPL(ccid_unregister);
88 149  
89   -struct ccid *ccid_init(unsigned char id, struct sock *sk)
  150 +struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx, gfp_t gfp)
90 151 {
91   - struct ccid *ccid;
  152 + struct ccid_operations *ccid_ops;
  153 + struct ccid *ccid = NULL;
92 154  
  155 + ccids_read_lock();
93 156 #ifdef CONFIG_KMOD
94   - if (ccids[id] == NULL)
  157 + if (ccids[id] == NULL) {
  158 + /* We only try to load if in process context */
  159 + ccids_read_unlock();
  160 + if (gfp & GFP_ATOMIC)
  161 + goto out;
95 162 request_module("net-dccp-ccid-%d", id);
  163 + ccids_read_lock();
  164 + }
96 165 #endif
97   - ccids_read_lock();
  166 + ccid_ops = ccids[id];
  167 + if (ccid_ops == NULL)
  168 + goto out_unlock;
98 169  
99   - ccid = ccids[id];
100   - if (ccid == NULL)
101   - goto out;
  170 + if (!try_module_get(ccid_ops->ccid_owner))
  171 + goto out_unlock;
102 172  
103   - if (!try_module_get(ccid->ccid_owner))
104   - goto out_err;
  173 + ccids_read_unlock();
105 174  
106   - if (ccid->ccid_init != NULL && ccid->ccid_init(sk) != 0)
  175 + ccid = kmem_cache_alloc(rx ? ccid_ops->ccid_hc_rx_slab :
  176 + ccid_ops->ccid_hc_tx_slab, gfp);
  177 + if (ccid == NULL)
107 178 goto out_module_put;
  179 + ccid->ccid_ops = ccid_ops;
  180 + if (rx) {
  181 + memset(ccid + 1, 0, ccid_ops->ccid_hc_rx_obj_size);
  182 + if (ccid->ccid_ops->ccid_hc_rx_init != NULL &&
  183 + ccid->ccid_ops->ccid_hc_rx_init(ccid, sk) != 0)
  184 + goto out_free_ccid;
  185 + } else {
  186 + memset(ccid + 1, 0, ccid_ops->ccid_hc_tx_obj_size);
  187 + if (ccid->ccid_ops->ccid_hc_tx_init != NULL &&
  188 + ccid->ccid_ops->ccid_hc_tx_init(ccid, sk) != 0)
  189 + goto out_free_ccid;
  190 + }
108 191 out:
109   - ccids_read_unlock();
110 192 return ccid;
111   -out_module_put:
112   - module_put(ccid->ccid_owner);
113   -out_err:
  193 +out_unlock:
  194 + ccids_read_unlock();
  195 + goto out;
  196 +out_free_ccid:
  197 + kmem_cache_free(rx ? ccid_ops->ccid_hc_rx_slab :
  198 + ccid_ops->ccid_hc_tx_slab, ccid);
114 199 ccid = NULL;
  200 +out_module_put:
  201 + module_put(ccid_ops->ccid_owner);
115 202 goto out;
116 203 }
117 204  
118   -EXPORT_SYMBOL_GPL(ccid_init);
  205 +EXPORT_SYMBOL_GPL(ccid_new);
119 206  
120   -void ccid_exit(struct ccid *ccid, struct sock *sk)
  207 +struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk, gfp_t gfp)
121 208 {
  209 + return ccid_new(id, sk, 1, gfp);
  210 +}
  211 +
  212 +EXPORT_SYMBOL_GPL(ccid_hc_rx_new);
  213 +
  214 +struct ccid *ccid_hc_tx_new(unsigned char id,struct sock *sk, gfp_t gfp)
  215 +{
  216 + return ccid_new(id, sk, 0, gfp);
  217 +}
  218 +
  219 +EXPORT_SYMBOL_GPL(ccid_hc_tx_new);
  220 +
  221 +static void ccid_delete(struct ccid *ccid, struct sock *sk, int rx)
  222 +{
  223 + struct ccid_operations *ccid_ops;
  224 +
122 225 if (ccid == NULL)
123 226 return;
124 227  
  228 + ccid_ops = ccid->ccid_ops;
  229 + if (rx) {
  230 + if (ccid_ops->ccid_hc_rx_exit != NULL)
  231 + ccid_ops->ccid_hc_rx_exit(sk);
  232 + kmem_cache_free(ccid_ops->ccid_hc_rx_slab, ccid);
  233 + } else {
  234 + if (ccid_ops->ccid_hc_tx_exit != NULL)
  235 + ccid_ops->ccid_hc_tx_exit(sk);
  236 + kmem_cache_free(ccid_ops->ccid_hc_tx_slab, ccid);
  237 + }
125 238 ccids_read_lock();
  239 + if (ccids[ccid_ops->ccid_id] != NULL)
  240 + module_put(ccid_ops->ccid_owner);
  241 + ccids_read_unlock();
  242 +}
126 243  
127   - if (ccids[ccid->ccid_id] != NULL) {
128   - if (ccid->ccid_exit != NULL)
129   - ccid->ccid_exit(sk);
130   - module_put(ccid->ccid_owner);
131   - }
  244 +void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk)
  245 +{
  246 + ccid_delete(ccid, sk, 1);
  247 +}
132 248  
133   - ccids_read_unlock();
  249 +EXPORT_SYMBOL_GPL(ccid_hc_rx_delete);
  250 +
  251 +void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk)
  252 +{
  253 + ccid_delete(ccid, sk, 0);
134 254 }
135 255  
136   -EXPORT_SYMBOL_GPL(ccid_exit);
  256 +EXPORT_SYMBOL_GPL(ccid_hc_tx_delete);
... ... @@ -23,14 +23,16 @@
23 23  
24 24 struct tcp_info;
25 25  
26   -struct ccid {
  26 +struct ccid_operations {
27 27 unsigned char ccid_id;
28 28 const char *ccid_name;
29 29 struct module *ccid_owner;
30   - int (*ccid_init)(struct sock *sk);
31   - void (*ccid_exit)(struct sock *sk);
32   - int (*ccid_hc_rx_init)(struct sock *sk);
33   - int (*ccid_hc_tx_init)(struct sock *sk);
  30 + kmem_cache_t *ccid_hc_rx_slab;
  31 + __u32 ccid_hc_rx_obj_size;
  32 + kmem_cache_t *ccid_hc_tx_slab;
  33 + __u32 ccid_hc_tx_obj_size;
  34 + int (*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
  35 + int (*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
34 36 void (*ccid_hc_rx_exit)(struct sock *sk);
35 37 void (*ccid_hc_tx_exit)(struct sock *sk);
36 38 void (*ccid_hc_rx_packet_recv)(struct sock *sk,
37 39  
38 40  
39 41  
40 42  
41 43  
42 44  
43 45  
44 46  
45 47  
... ... @@ -67,75 +69,58 @@
67 69 int __user *optlen);
68 70 };
69 71  
70   -extern int ccid_register(struct ccid *ccid);
71   -extern int ccid_unregister(struct ccid *ccid);
  72 +extern int ccid_register(struct ccid_operations *ccid_ops);
  73 +extern int ccid_unregister(struct ccid_operations *ccid_ops);
72 74  
73   -extern struct ccid *ccid_init(unsigned char id, struct sock *sk);
74   -extern void ccid_exit(struct ccid *ccid, struct sock *sk);
  75 +struct ccid {
  76 + struct ccid_operations *ccid_ops;
  77 + char ccid_priv[0];
  78 +};
75 79  
76   -static inline void __ccid_get(struct ccid *ccid)
  80 +static inline void *ccid_priv(const struct ccid *ccid)
77 81 {
78   - __module_get(ccid->ccid_owner);
  82 + return (void *)ccid->ccid_priv;
79 83 }
80 84  
  85 +extern struct ccid *ccid_new(unsigned char id, struct sock *sk, int rx,
  86 + gfp_t gfp);
  87 +
  88 +extern struct ccid *ccid_hc_rx_new(unsigned char id, struct sock *sk,
  89 + gfp_t gfp);
  90 +extern struct ccid *ccid_hc_tx_new(unsigned char id, struct sock *sk,
  91 + gfp_t gfp);
  92 +
  93 +extern void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
  94 +extern void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
  95 +
81 96 static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
82 97 struct sk_buff *skb, int len)
83 98 {
84 99 int rc = 0;
85   - if (ccid->ccid_hc_tx_send_packet != NULL)
86   - rc = ccid->ccid_hc_tx_send_packet(sk, skb, len);
  100 + if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
  101 + rc = ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb, len);
87 102 return rc;
88 103 }
89 104  
90 105 static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
91 106 int more, int len)
92 107 {
93   - if (ccid->ccid_hc_tx_packet_sent != NULL)
94   - ccid->ccid_hc_tx_packet_sent(sk, more, len);
  108 + if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
  109 + ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, more, len);
95 110 }
96 111  
97   -static inline int ccid_hc_rx_init(struct ccid *ccid, struct sock *sk)
98   -{
99   - int rc = 0;
100   - if (ccid->ccid_hc_rx_init != NULL)
101   - rc = ccid->ccid_hc_rx_init(sk);
102   - return rc;
103   -}
104   -
105   -static inline int ccid_hc_tx_init(struct ccid *ccid, struct sock *sk)
106   -{
107   - int rc = 0;
108   - if (ccid->ccid_hc_tx_init != NULL)
109   - rc = ccid->ccid_hc_tx_init(sk);
110   - return rc;
111   -}
112   -
113   -static inline void ccid_hc_rx_exit(struct ccid *ccid, struct sock *sk)
114   -{
115   - if (ccid != NULL && ccid->ccid_hc_rx_exit != NULL &&
116   - dccp_sk(sk)->dccps_hc_rx_ccid_private != NULL)
117   - ccid->ccid_hc_rx_exit(sk);
118   -}
119   -
120   -static inline void ccid_hc_tx_exit(struct ccid *ccid, struct sock *sk)
121   -{
122   - if (ccid != NULL && ccid->ccid_hc_tx_exit != NULL &&
123   - dccp_sk(sk)->dccps_hc_tx_ccid_private != NULL)
124   - ccid->ccid_hc_tx_exit(sk);
125   -}
126   -
127 112 static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
128 113 struct sk_buff *skb)
129 114 {
130   - if (ccid->ccid_hc_rx_packet_recv != NULL)
131   - ccid->ccid_hc_rx_packet_recv(sk, skb);
  115 + if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
  116 + ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
132 117 }
133 118  
134 119 static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
135 120 struct sk_buff *skb)
136 121 {
137   - if (ccid->ccid_hc_tx_packet_recv != NULL)
138   - ccid->ccid_hc_tx_packet_recv(sk, skb);
  122 + if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
  123 + ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
139 124 }
140 125  
141 126 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
... ... @@ -144,8 +129,8 @@
144 129 unsigned char* value)
145 130 {
146 131 int rc = 0;
147   - if (ccid->ccid_hc_tx_parse_options != NULL)
148   - rc = ccid->ccid_hc_tx_parse_options(sk, option, len, idx,
  132 + if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL)
  133 + rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx,
149 134 value);
150 135 return rc;
151 136 }
152 137  
153 138  
154 139  
155 140  
... ... @@ -156,37 +141,37 @@
156 141 unsigned char* value)
157 142 {
158 143 int rc = 0;
159   - if (ccid->ccid_hc_rx_parse_options != NULL)
160   - rc = ccid->ccid_hc_rx_parse_options(sk, option, len, idx, value);
  144 + if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL)
  145 + rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value);
161 146 return rc;
162 147 }
163 148  
164 149 static inline void ccid_hc_tx_insert_options(struct ccid *ccid, struct sock *sk,
165 150 struct sk_buff *skb)
166 151 {
167   - if (ccid->ccid_hc_tx_insert_options != NULL)
168   - ccid->ccid_hc_tx_insert_options(sk, skb);
  152 + if (ccid->ccid_ops->ccid_hc_tx_insert_options != NULL)
  153 + ccid->ccid_ops->ccid_hc_tx_insert_options(sk, skb);
169 154 }
170 155  
171 156 static inline void ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
172 157 struct sk_buff *skb)
173 158 {
174   - if (ccid->ccid_hc_rx_insert_options != NULL)
175   - ccid->ccid_hc_rx_insert_options(sk, skb);
  159 + if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
  160 + ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
176 161 }
177 162  
178 163 static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
179 164 struct tcp_info *info)
180 165 {
181   - if (ccid->ccid_hc_rx_get_info != NULL)
182   - ccid->ccid_hc_rx_get_info(sk, info);
  166 + if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
  167 + ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
183 168 }
184 169  
185 170 static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
186 171 struct tcp_info *info)
187 172 {
188   - if (ccid->ccid_hc_tx_get_info != NULL)
189   - ccid->ccid_hc_tx_get_info(sk, info);
  173 + if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
  174 + ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
190 175 }
191 176  
192 177 static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
... ... @@ -194,8 +179,8 @@
194 179 u32 __user *optval, int __user *optlen)
195 180 {
196 181 int rc = -ENOPROTOOPT;
197   - if (ccid->ccid_hc_rx_getsockopt != NULL)
198   - rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len,
  182 + if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
  183 + rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
199 184 optval, optlen);
200 185 return rc;
201 186 }
... ... @@ -205,8 +190,8 @@
205 190 u32 __user *optval, int __user *optlen)
206 191 {
207 192 int rc = -ENOPROTOOPT;
208   - if (ccid->ccid_hc_tx_getsockopt != NULL)
209   - rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len,
  193 + if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
  194 + rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
210 195 optval, optlen);
211 196 return rc;
212 197 }
net/dccp/ccids/ccid2.c
... ... @@ -52,16 +52,6 @@
52 52  
53 53 static const int ccid2_seq_len = 128;
54 54  
55   -static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
56   -{
57   - return dccp_sk(sk)->dccps_hc_tx_ccid_private;
58   -}
59   -
60   -static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
61   -{
62   - return dccp_sk(sk)->dccps_hc_rx_ccid_private;
63   -}
64   -
65 55 #ifdef CCID2_DEBUG
66 56 static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
67 57 {
68 58  
69 59  
... ... @@ -707,19 +697,12 @@
707 697 ccid2_hc_tx_check_sanity(hctx);
708 698 }
709 699  
710   -static int ccid2_hc_tx_init(struct sock *sk)
  700 +static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
711 701 {
712   - struct dccp_sock *dp = dccp_sk(sk);
713   - struct ccid2_hc_tx_sock *hctx;
  702 + struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
714 703 int seqcount = ccid2_seq_len;
715 704 int i;
716 705  
717   - dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any());
718   - if (dp->dccps_hc_tx_ccid_private == NULL)
719   - return -ENOMEM;
720   -
721   - hctx = ccid2_hc_tx_sk(sk);
722   -
723 706 /* XXX init variables with proper values */
724 707 hctx->ccid2hctx_cwnd = 1;
725 708 hctx->ccid2hctx_ssthresh = 10;
726 709  
... ... @@ -728,11 +711,9 @@
728 711 /* XXX init ~ to window size... */
729 712 hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
730 713 seqcount, gfp_any());
731   - if (hctx->ccid2hctx_seqbuf == NULL) {
732   - kfree(dp->dccps_hc_tx_ccid_private);
733   - dp->dccps_hc_tx_ccid_private = NULL;
  714 + if (hctx->ccid2hctx_seqbuf == NULL)
734 715 return -ENOMEM;
735   - }
  716 +
736 717 for (i = 0; i < (seqcount - 1); i++) {
737 718 hctx->ccid2hctx_seqbuf[i].ccid2s_next =
738 719 &hctx->ccid2hctx_seqbuf[i + 1];
739 720  
740 721  
... ... @@ -763,15 +744,11 @@
763 744  
764 745 static void ccid2_hc_tx_exit(struct sock *sk)
765 746 {
766   - struct dccp_sock *dp = dccp_sk(sk);
767 747 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
768 748  
769 749 ccid2_hc_tx_kill_rto_timer(sk);
770   -
771 750 kfree(hctx->ccid2hctx_seqbuf);
772   -
773   - kfree(dp->dccps_hc_tx_ccid_private);
774   - dp->dccps_hc_tx_ccid_private = NULL;
  751 + hctx->ccid2hctx_seqbuf = NULL;
775 752 }
776 753  
777 754 static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
778 755  
779 756  
... ... @@ -791,33 +768,17 @@
791 768 }
792 769 }
793 770  
794   -static int ccid2_hc_rx_init(struct sock *sk)
795   -{
796   - struct dccp_sock *dp = dccp_sk(sk);
797   - dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock),
798   - gfp_any());
799   - return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0;
800   -}
801   -
802   -static void ccid2_hc_rx_exit(struct sock *sk)
803   -{
804   - struct dccp_sock *dp = dccp_sk(sk);
805   -
806   - kfree(dp->dccps_hc_rx_ccid_private);
807   - dp->dccps_hc_rx_ccid_private = NULL;
808   -}
809   -
810   -static struct ccid ccid2 = {
  771 +static struct ccid_operations ccid2 = {
811 772 .ccid_id = 2,
812 773 .ccid_name = "ccid2",
813 774 .ccid_owner = THIS_MODULE,
  775 + .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
814 776 .ccid_hc_tx_init = ccid2_hc_tx_init,
815 777 .ccid_hc_tx_exit = ccid2_hc_tx_exit,
816 778 .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
817 779 .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
818 780 .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
819   - .ccid_hc_rx_init = ccid2_hc_rx_init,
820   - .ccid_hc_rx_exit = ccid2_hc_rx_exit,
  781 + .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
821 782 .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
822 783 };
823 784  
net/dccp/ccids/ccid2.h
... ... @@ -20,6 +20,13 @@
20 20 #ifndef _DCCP_CCID2_H_
21 21 #define _DCCP_CCID2_H_
22 22  
  23 +#include <linux/dccp.h>
  24 +#include <linux/timer.h>
  25 +#include <linux/types.h>
  26 +#include "../ccid.h"
  27 +
  28 +struct sock;
  29 +
23 30 struct ccid2_seq {
24 31 u64 ccid2s_seq;
25 32 unsigned long ccid2s_sent;
... ... @@ -66,5 +73,14 @@
66 73 int ccid2hcrx_data;
67 74 };
68 75  
  76 +static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
  77 +{
  78 + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
  79 +}
  80 +
  81 +static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
  82 +{
  83 + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
  84 +}
69 85 #endif /* _DCCP_CCID2_H_ */
net/dccp/ccids/ccid3.c
... ... @@ -647,18 +647,11 @@
647 647 return rc;
648 648 }
649 649  
650   -static int ccid3_hc_tx_init(struct sock *sk)
  650 +static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
651 651 {
652 652 struct dccp_sock *dp = dccp_sk(sk);
653   - struct ccid3_hc_tx_sock *hctx;
  653 + struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
654 654  
655   - dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any());
656   - if (dp->dccps_hc_tx_ccid_private == NULL)
657   - return -ENOMEM;
658   -
659   - hctx = ccid3_hc_tx_sk(sk);
660   - memset(hctx, 0, sizeof(*hctx));
661   -
662 655 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
663 656 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
664 657 hctx->ccid3hctx_s = dp->dccps_packet_size;
... ... @@ -680,7 +673,6 @@
680 673  
681 674 static void ccid3_hc_tx_exit(struct sock *sk)
682 675 {
683   - struct dccp_sock *dp = dccp_sk(sk);
684 676 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
685 677  
686 678 BUG_ON(hctx == NULL);
... ... @@ -690,9 +682,6 @@
690 682  
691 683 /* Empty packet history */
692 684 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
693   -
694   - kfree(dp->dccps_hc_tx_ccid_private);
695   - dp->dccps_hc_tx_ccid_private = NULL;
696 685 }
697 686  
698 687 /*
699 688  
700 689  
... ... @@ -1039,20 +1028,13 @@
1039 1028 }
1040 1029 }
1041 1030  
1042   -static int ccid3_hc_rx_init(struct sock *sk)
  1031 +static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
1043 1032 {
1044 1033 struct dccp_sock *dp = dccp_sk(sk);
1045   - struct ccid3_hc_rx_sock *hcrx;
  1034 + struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
1046 1035  
1047 1036 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1048 1037  
1049   - dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any());
1050   - if (dp->dccps_hc_rx_ccid_private == NULL)
1051   - return -ENOMEM;
1052   -
1053   - hcrx = ccid3_hc_rx_sk(sk);
1054   - memset(hcrx, 0, sizeof(*hcrx));
1055   -
1056 1038 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
1057 1039 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
1058 1040 hcrx->ccid3hcrx_s = dp->dccps_packet_size;
... ... @@ -1071,7 +1053,6 @@
1071 1053 static void ccid3_hc_rx_exit(struct sock *sk)
1072 1054 {
1073 1055 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1074   - struct dccp_sock *dp = dccp_sk(sk);
1075 1056  
1076 1057 BUG_ON(hcrx == NULL);
1077 1058  
... ... @@ -1082,9 +1063,6 @@
1082 1063  
1083 1064 /* Empty loss interval history */
1084 1065 dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
1085   -
1086   - kfree(dp->dccps_hc_rx_ccid_private);
1087   - dp->dccps_hc_rx_ccid_private = NULL;
1088 1066 }
1089 1067  
1090 1068 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
1091 1069  
... ... @@ -1170,10 +1148,11 @@
1170 1148 return 0;
1171 1149 }
1172 1150  
1173   -static struct ccid ccid3 = {
  1151 +static struct ccid_operations ccid3 = {
1174 1152 .ccid_id = 3,
1175 1153 .ccid_name = "ccid3",
1176 1154 .ccid_owner = THIS_MODULE,
  1155 + .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock),
1177 1156 .ccid_hc_tx_init = ccid3_hc_tx_init,
1178 1157 .ccid_hc_tx_exit = ccid3_hc_tx_exit,
1179 1158 .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
... ... @@ -1181,6 +1160,7 @@
1181 1160 .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
1182 1161 .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
1183 1162 .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
  1163 + .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock),
1184 1164 .ccid_hc_rx_init = ccid3_hc_rx_init,
1185 1165 .ccid_hc_rx_exit = ccid3_hc_rx_exit,
1186 1166 .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
net/dccp/ccids/ccid3.h
... ... @@ -41,6 +41,7 @@
41 41 #include <linux/time.h>
42 42 #include <linux/types.h>
43 43 #include <linux/tfrc.h>
  44 +#include "../ccid.h"
44 45  
45 46 #define TFRC_MIN_PACKET_SIZE 16
46 47 #define TFRC_STD_PACKET_SIZE 256
47 48  
... ... @@ -135,12 +136,12 @@
135 136  
136 137 static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk)
137 138 {
138   - return dccp_sk(sk)->dccps_hc_tx_ccid_private;
  139 + return ccid_priv(dccp_sk(sk)->dccps_hc_tx_ccid);
139 140 }
140 141  
141 142 static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
142 143 {
143   - return dccp_sk(sk)->dccps_hc_rx_ccid_private;
  144 + return ccid_priv(dccp_sk(sk)->dccps_hc_rx_ccid);
144 145 }
145 146  
146 147 #endif /* _DCCP_CCID3_H_ */
... ... @@ -324,14 +324,6 @@
324 324 dccp_set_seqno(&dp->dccps_swl,
325 325 max48(dp->dccps_swl, dp->dccps_isr));
326 326  
327   - if (ccid_hc_rx_init(dp->dccps_hc_rx_ccid, sk) != 0 ||
328   - ccid_hc_tx_init(dp->dccps_hc_tx_ccid, sk) != 0) {
329   - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
330   - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
331   - /* FIXME: send appropriate RESET code */
332   - goto out_invalid_packet;
333   - }
334   -
335 327 dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
336 328  
337 329 /*
... ... @@ -1058,14 +1058,16 @@
1058 1058 if (dp->dccps_hc_rx_ackvec == NULL)
1059 1059 return -ENOMEM;
1060 1060 }
1061   - dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid,
1062   - sk);
1063   - dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid,
1064   - sk);
1065   - if (dp->dccps_hc_rx_ccid == NULL ||
1066   - dp->dccps_hc_tx_ccid == NULL) {
1067   - ccid_exit(dp->dccps_hc_rx_ccid, sk);
1068   - ccid_exit(dp->dccps_hc_tx_ccid, sk);
  1061 + dp->dccps_hc_rx_ccid =
  1062 + ccid_hc_rx_new(dp->dccps_options.dccpo_rx_ccid,
  1063 + sk, GFP_KERNEL);
  1064 + dp->dccps_hc_tx_ccid =
  1065 + ccid_hc_tx_new(dp->dccps_options.dccpo_tx_ccid,
  1066 + sk, GFP_KERNEL);
  1067 + if (unlikely(dp->dccps_hc_rx_ccid == NULL ||
  1068 + dp->dccps_hc_tx_ccid == NULL)) {
  1069 + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
  1070 + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
1069 1071 if (dp->dccps_options.dccpo_send_ack_vector) {
1070 1072 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1071 1073 dp->dccps_hc_rx_ackvec = NULL;
1072 1074  
... ... @@ -1120,14 +1122,12 @@
1120 1122 kfree(dp->dccps_service_list);
1121 1123 dp->dccps_service_list = NULL;
1122 1124  
1123   - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk);
1124   - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk);
1125 1125 if (dp->dccps_options.dccpo_send_ack_vector) {
1126 1126 dccp_ackvec_free(dp->dccps_hc_rx_ackvec);
1127 1127 dp->dccps_hc_rx_ackvec = NULL;
1128 1128 }
1129   - ccid_exit(dp->dccps_hc_rx_ccid, sk);
1130   - ccid_exit(dp->dccps_hc_tx_ccid, sk);
  1129 + ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
  1130 + ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
1131 1131 dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
1132 1132  
1133 1133 /* clean up feature negotiation state */
net/dccp/minisocks.c
... ... @@ -121,23 +121,21 @@
121 121 if (newdp->dccps_options.dccpo_send_ack_vector) {
122 122 newdp->dccps_hc_rx_ackvec =
123 123 dccp_ackvec_alloc(GFP_ATOMIC);
124   - /*
125   - * XXX: We're using the same CCIDs set on the parent,
126   - * i.e. sk_clone copied the master sock and left the
127   - * CCID pointers for this child, that is why we do the
128   - * __ccid_get calls.
129   - */
130 124 if (unlikely(newdp->dccps_hc_rx_ackvec == NULL))
131 125 goto out_free;
132 126 }
133 127  
134   - if (unlikely(ccid_hc_rx_init(newdp->dccps_hc_rx_ccid,
135   - newsk) != 0 ||
136   - ccid_hc_tx_init(newdp->dccps_hc_tx_ccid,
137   - newsk) != 0)) {
  128 + newdp->dccps_hc_rx_ccid =
  129 + ccid_hc_rx_new(newdp->dccps_options.dccpo_rx_ccid,
  130 + newsk, GFP_ATOMIC);
  131 + newdp->dccps_hc_tx_ccid =
  132 + ccid_hc_tx_new(newdp->dccps_options.dccpo_tx_ccid,
  133 + newsk, GFP_ATOMIC);
  134 + if (unlikely(newdp->dccps_hc_rx_ccid == NULL ||
  135 + newdp->dccps_hc_tx_ccid == NULL)) {
138 136 dccp_ackvec_free(newdp->dccps_hc_rx_ackvec);
139   - ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk);
140   - ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk);
  137 + ccid_hc_rx_delete(newdp->dccps_hc_rx_ccid, newsk);
  138 + ccid_hc_tx_delete(newdp->dccps_hc_tx_ccid, newsk);
141 139 out_free:
142 140 /* It is still raw copy of parent, so invalidate
143 141 * destructor and make plain sk_free() */
... ... @@ -145,9 +143,6 @@
145 143 sk_free(newsk);
146 144 return NULL;
147 145 }
148   -
149   - __ccid_get(newdp->dccps_hc_rx_ccid);
150   - __ccid_get(newdp->dccps_hc_tx_ccid);
151 146  
152 147 /*
153 148 * Step 3: Process LISTEN state