diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:30:19 -0400 |
---|---|---|
committer | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-09-04 01:45:30 -0400 |
commit | 3a53a9adfa269da7fa40fc476f09e46155c0143d (patch) | |
tree | 9090efbd2aa9cc24ea50c63336a029e018509529 /net/dccp/proto.c | |
parent | c926c6aed3e444e8c88a768f063b2de8fd6ae760 (diff) |
dccp: Integration of dynamic feature activation - part 1 (socket setup)
This first patch out of three replaces the hardcoded default settings with
initialisation code for the dynamic feature negotiation.
Note on retransmitting Confirm options:
---------------------------------------
This patch also defers flushing the client feature-negotiation queue,
due to the following considerations.
As long as the client is in PARTOPEN, it needs to retransmit the Confirm
options for the Change options received on the DCCP-Response from the server.
Otherwise, if the packet containing the Confirm options gets dropped in the
network, the connection aborts due to undefined feature negotiation state.
Thanks to Leandro Melo de Sales who reported a bug in an earlier revision
of the patch set, resulting from not retransmitting the Confirm options.
The patch now ensures that the client feature-negotiation queue is flushed only
when entering the OPEN state. Since confirmed Change options are removed as
soon as they are confirmed (in the DCCP-Response), this ensures that Confirm
options are retransmitted.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r-- | net/dccp/proto.c | 46 |
1 files changed, 6 insertions, 40 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 6550452d59e2..0d420790b795 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -67,6 +67,9 @@ void dccp_set_state(struct sock *sk, const int state) | |||
67 | case DCCP_OPEN: | 67 | case DCCP_OPEN: |
68 | if (oldstate != DCCP_OPEN) | 68 | if (oldstate != DCCP_OPEN) |
69 | DCCP_INC_STATS(DCCP_MIB_CURRESTAB); | 69 | DCCP_INC_STATS(DCCP_MIB_CURRESTAB); |
70 | /* Client retransmits all Confirm options until entering OPEN */ | ||
71 | if (oldstate == DCCP_PARTOPEN) | ||
72 | dccp_feat_list_purge(&dccp_sk(sk)->dccps_featneg); | ||
70 | break; | 73 | break; |
71 | 74 | ||
72 | case DCCP_CLOSED: | 75 | case DCCP_CLOSED: |
@@ -175,7 +178,6 @@ EXPORT_SYMBOL_GPL(dccp_state_name); | |||
175 | int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) | 178 | int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) |
176 | { | 179 | { |
177 | struct dccp_sock *dp = dccp_sk(sk); | 180 | struct dccp_sock *dp = dccp_sk(sk); |
178 | struct dccp_minisock *dmsk = dccp_msk(sk); | ||
179 | struct inet_connection_sock *icsk = inet_csk(sk); | 181 | struct inet_connection_sock *icsk = inet_csk(sk); |
180 | 182 | ||
181 | dccp_minisock_init(&dp->dccps_minisock); | 183 | dccp_minisock_init(&dp->dccps_minisock); |
@@ -194,45 +196,9 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) | |||
194 | dccp_init_xmit_timers(sk); | 196 | dccp_init_xmit_timers(sk); |
195 | 197 | ||
196 | INIT_LIST_HEAD(&dp->dccps_featneg); | 198 | INIT_LIST_HEAD(&dp->dccps_featneg); |
197 | /* | 199 | /* control socket doesn't need feat nego */ |
198 | * FIXME: We're hardcoding the CCID, and doing this at this point makes | 200 | if (likely(ctl_sock_initialized)) |
199 | * the listening (master) sock get CCID control blocks, which is not | 201 | return dccp_feat_init(sk); |
200 | * necessary, but for now, to not mess with the test userspace apps, | ||
201 | * lets leave it here, later the real solution is to do this in a | ||
202 | * setsockopt(CCIDs-I-want/accept). -acme | ||
203 | */ | ||
204 | if (likely(ctl_sock_initialized)) { | ||
205 | int rc = dccp_feat_init(sk); | ||
206 | |||
207 | if (rc) | ||
208 | return rc; | ||
209 | |||
210 | if (dmsk->dccpms_send_ack_vector) { | ||
211 | dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(GFP_KERNEL); | ||
212 | if (dp->dccps_hc_rx_ackvec == NULL) | ||
213 | return -ENOMEM; | ||
214 | } | ||
215 | dp->dccps_hc_rx_ccid = ccid_hc_rx_new(dmsk->dccpms_rx_ccid, | ||
216 | sk, GFP_KERNEL); | ||
217 | dp->dccps_hc_tx_ccid = ccid_hc_tx_new(dmsk->dccpms_tx_ccid, | ||
218 | sk, GFP_KERNEL); | ||
219 | if (unlikely(dp->dccps_hc_rx_ccid == NULL || | ||
220 | dp->dccps_hc_tx_ccid == NULL)) { | ||
221 | ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); | ||
222 | ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); | ||
223 | if (dmsk->dccpms_send_ack_vector) { | ||
224 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); | ||
225 | dp->dccps_hc_rx_ackvec = NULL; | ||
226 | } | ||
227 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | ||
228 | return -ENOMEM; | ||
229 | } | ||
230 | } else { | ||
231 | /* control socket doesn't need feat nego */ | ||
232 | INIT_LIST_HEAD(&dmsk->dccpms_pending); | ||
233 | INIT_LIST_HEAD(&dmsk->dccpms_conf); | ||
234 | } | ||
235 | |||
236 | return 0; | 202 | return 0; |
237 | } | 203 | } |
238 | 204 | ||