ccid3.c 32.1 KB
Newer Older
1 2 3
/*
 *  net/dccp/ccids/ccid3.c
 *
I
Ian McDonald 已提交
4 5
 *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
 *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
 *
 *  An implementation of the DCCP protocol
 *
 *  This code has been developed by the University of Waikato WAND
 *  research group. For further information please see http://www.wand.net.nz/
 *
 *  This code also uses code from Lulea University, rereleased as GPL by its
 *  authors:
 *  Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
 *
 *  Changes to meet Linux coding standards, to make it meet latest ccid3 draft
 *  and to make it work as a loadable module in the DCCP stack written by
 *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
 *
 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include "../ccid.h"
#include "../dccp.h"
38
#include "lib/packet_history.h"
39
#include "lib/loss_interval.h"
40
#include "lib/tfrc.h"
41 42
#include "ccid3.h"

43 44 45
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static int ccid3_debug;
#define ccid3_pr_debug(format, a...)	DCCP_PR_DEBUG(ccid3_debug, format, ##a)
46 47 48 49
#else
#define ccid3_pr_debug(format, a...)
#endif

50 51
static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
52

53 54 55
/*
 *	Transmitter Half-Connection Routines
 */
56
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
57 58 59 60 61 62 63 64 65 66 67 68 69
static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
{
	static char *ccid3_state_names[] = {
	[TFRC_SSTATE_NO_SENT]  = "NO_SENT",
	[TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
	[TFRC_SSTATE_FBACK]    = "FBACK",
	[TFRC_SSTATE_TERM]     = "TERM",
	};

	return ccid3_state_names[state];
}
#endif

70 71
static void ccid3_hc_tx_set_state(struct sock *sk,
				  enum ccid3_hc_tx_states state)
72
{
73
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
74 75 76
	enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
77 78
		       dccp_role(sk), sk, ccid3_tx_state_name(oldstate),
		       ccid3_tx_state_name(state));
79 80 81 82
	WARN_ON(state == oldstate);
	hctx->ccid3hctx_state = state;
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/*
 * Compute the initial sending rate X_init according to RFC 3390:
 *	w_init   =    min(4 * MSS, max(2 * MSS, 4380 bytes))
 *	X_init   =    w_init / RTT
 * For consistency with other parts of the code, X_init is scaled by 2^6.
 */
static inline u64 rfc3390_initial_rate(struct sock *sk)
{
	const struct dccp_sock *dp = dccp_sk(sk);
	const __u32 w_init = min(4 * dp->dccps_mss_cache,
				 max(2 * dp->dccps_mss_cache, 4380U));

	return scaled_div(w_init << 6, ccid3_hc_tx_sk(sk)->ccid3hctx_rtt);
}

98
/*
99
 * Recalculate t_ipi and delta (should be called whenever X changes)
100
 */
101
static inline void ccid3_update_send_interval(struct ccid3_hc_tx_sock *hctx)
102
{
103
	/* Calculate new t_ipi = s / X_inst (X_inst is in 64 * bytes/second) */
104 105
	hctx->ccid3hctx_t_ipi = scaled_div32(((u64)hctx->ccid3hctx_s) << 6,
					     hctx->ccid3hctx_x);
106

107
	/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
108 109
	hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
					   TFRC_OPSYS_HALF_TIME_GRAN);
I
Ian McDonald 已提交
110

111
	ccid3_pr_debug("t_ipi=%u, delta=%u, s=%u, X=%u\n",
I
Ian McDonald 已提交
112
		       hctx->ccid3hctx_t_ipi, hctx->ccid3hctx_delta,
113
		       hctx->ccid3hctx_s, (unsigned)(hctx->ccid3hctx_x >> 6));
I
Ian McDonald 已提交
114

115 116 117 118
}
/*
 * Update X by
 *    If (p > 0)
119
 *       X_calc = calcX(s, R, p);
120 121 122 123 124
 *       X = max(min(X_calc, 2 * X_recv), s / t_mbi);
 *    Else
 *       If (now - tld >= R)
 *          X = max(min(2 * X, 2 * X_recv), s / R);
 *          tld = now;
125
 *
126 127 128 129 130
 * Note: X and X_recv are both stored in units of 64 * bytes/second, to support
 *       fine-grained resolution of sending rates. This requires scaling by 2^6
 *       throughout the code. Only X_calc is unscaled (in bytes/second).
 *
 */
131
static void ccid3_hc_tx_update_x(struct sock *sk)
132

133
{
134
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
135
	__u64 min_rate = 2 * hctx->ccid3hctx_x_recv;
136
	const  __u64 old_x = hctx->ccid3hctx_x;
137

138 139 140 141 142 143 144 145 146 147
	/*
	 * Handle IDLE periods: do not reduce below RFC3390 initial sending rate
	 * when idling [RFC 4342, 5.1]. See also draft-ietf-dccp-rfc3448bis.
	 * For consistency with X and X_recv, min_rate is also scaled by 2^6.
	 */
	if (unlikely(hctx->ccid3hctx_idle)) {
		min_rate = rfc3390_initial_rate(sk);
		min_rate = max(min_rate, 2 * hctx->ccid3hctx_x_recv);
	}

148
	if (hctx->ccid3hctx_p > 0) {
149

150
		hctx->ccid3hctx_x = min(((__u64)hctx->ccid3hctx_x_calc) << 6,
151
					min_rate);
152 153
		hctx->ccid3hctx_x = max(hctx->ccid3hctx_x,
					(((__u64)hctx->ccid3hctx_s) << 6) /
154
								TFRC_T_MBI);
155

156
	} else {
157
		const ktime_t now = ktime_get_real();
158

159 160
		if ((ktime_us_delta(now, hctx->ccid3hctx_t_ld) -
		     (s64)hctx->ccid3hctx_rtt) >= 0) {
161 162 163 164 165 166 167

			hctx->ccid3hctx_x =
				max(min(2 * hctx->ccid3hctx_x, min_rate),
				    scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
					       hctx->ccid3hctx_rtt));
			hctx->ccid3hctx_t_ld = now;
		}
168
	}
169

I
Ian McDonald 已提交
170
	if (hctx->ccid3hctx_x != old_x) {
171 172 173 174 175
		ccid3_pr_debug("X_prev=%u, X_now=%u, X_calc=%u, "
			       "X_recv=%u\n", (unsigned)(old_x >> 6),
			       (unsigned)(hctx->ccid3hctx_x >> 6),
			       hctx->ccid3hctx_x_calc,
			       (unsigned)(hctx->ccid3hctx_x_recv >> 6));
I
Ian McDonald 已提交
176

177
		ccid3_update_send_interval(hctx);
I
Ian McDonald 已提交
178
	}
179 180
}

181
/*
182 183
 *	Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
 *	@len: DCCP packet payload size in bytes
184 185 186
 */
static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
{
187 188 189 190 191 192
	const u16 old_s = hctx->ccid3hctx_s;

	hctx->ccid3hctx_s = old_s == 0 ? len : (9 * old_s + len) / 10;

	if (hctx->ccid3hctx_s != old_s)
		ccid3_update_send_interval(hctx);
193 194
}

195
/*
196 197
 *	Update Window Counter using the algorithm from [RFC 4342, 8.1].
 *	The algorithm is not applicable if RTT < 4 microseconds.
198 199
 */
static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
200
						ktime_t now)
201 202 203 204 205 206
{
	u32 quarter_rtts;

	if (unlikely(hctx->ccid3hctx_rtt < 4))	/* avoid divide-by-zero */
		return;

207 208
	quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
	quarter_rtts /= hctx->ccid3hctx_rtt / 4;
209 210

	if (quarter_rtts > 0) {
211
		hctx->ccid3hctx_t_last_win_count = now;
212 213 214 215 216
		hctx->ccid3hctx_last_win_count	+= min_t(u32, quarter_rtts, 5);
		hctx->ccid3hctx_last_win_count	&= 0xF;		/* mod 16 */
	}
}

217 218 219
static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
	struct sock *sk = (struct sock *)data;
220
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
221
	unsigned long t_nfb = USEC_PER_SEC / 5;
222 223 224 225 226

	bh_lock_sock(sk);
	if (sock_owned_by_user(sk)) {
		/* Try again later. */
		/* XXX: set some sensible MIB */
227
		goto restart_timer;
228 229
	}

230
	ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk,
231
		       ccid3_tx_state_name(hctx->ccid3hctx_state));
232

233 234
	hctx->ccid3hctx_idle = 1;

235 236
	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_FBACK:
237
		/* RFC 3448, 4.4: Halve send rate directly */
238 239 240
		hctx->ccid3hctx_x = max(hctx->ccid3hctx_x / 2,
					(((__u64)hctx->ccid3hctx_s) << 6) /
								    TFRC_T_MBI);
241

242 243
		ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
			       "bytes/s\n", dccp_role(sk), sk,
244
			       ccid3_tx_state_name(hctx->ccid3hctx_state),
245
			       (unsigned)(hctx->ccid3hctx_x >> 6));
246 247
		/* The value of R is still undefined and so we can not recompute
		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
248
		t_nfb = TFRC_INITIAL_TIMEOUT;
249
		ccid3_update_send_interval(hctx);
250 251
		break;
	case TFRC_SSTATE_FBACK:
252
		/*
253 254 255 256 257 258 259 260
		 *  Modify the cached value of X_recv [RFC 3448, 4.4]
		 *
		 *  If (p == 0 || X_calc > 2 * X_recv)
		 *    X_recv = max(X_recv / 2, s / (2 * t_mbi));
		 *  Else
		 *    X_recv = X_calc / 4;
		 *
		 *  Note that X_recv is scaled by 2^6 while X_calc is not
261
		 */
262 263 264 265 266 267 268 269 270 271 272 273
		BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);

		if (hctx->ccid3hctx_p == 0 ||
		    (hctx->ccid3hctx_x_calc > (hctx->ccid3hctx_x_recv >> 5))) {

			hctx->ccid3hctx_x_recv =
				max(hctx->ccid3hctx_x_recv / 2,
				    (((__u64)hctx->ccid3hctx_s) << 6) /
							      (2 * TFRC_T_MBI));
		} else {
			hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc;
			hctx->ccid3hctx_x_recv <<= 4;
274
		}
275
		/* Now recalculate X [RFC 3448, 4.3, step (4)] */
276
		ccid3_hc_tx_update_x(sk);
277 278
		/*
		 * Schedule no feedback timer to expire in
279 280
		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
		 * See comments in packet_recv() regarding the value of t_RTO.
281
		 */
282
		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
283
		break;
284
	case TFRC_SSTATE_NO_SENT:
285
		DCCP_BUG("%s(%p) - Illegal state NO_SENT", dccp_role(sk), sk);
286 287
		/* fall through */
	case TFRC_SSTATE_TERM:
288 289 290
		goto out;
	}

291 292
restart_timer:
	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
293
			   jiffies + usecs_to_jiffies(t_nfb));
294 295 296 297 298
out:
	bh_unlock_sock(sk);
	sock_put(sk);
}

299 300 301 302 303 304
/*
 * returns
 *   > 0: delay (in msecs) that should pass before actually sending
 *   = 0: can send immediately
 *   < 0: error condition; do not send packet
 */
305
static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
306 307
{
	struct dccp_sock *dp = dccp_sk(sk);
308
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
309 310
	ktime_t now = ktime_get_real();
	s64 delay;
311

312
	BUG_ON(hctx == NULL);
313

314
	/*
315 316 317
	 * This function is called only for Data and DataAck packets. Sending
	 * zero-sized Data(Ack)s is theoretically possible, but for congestion
	 * control this case is pathological - ignore it.
318
	 */
319
	if (unlikely(skb->len == 0))
320
		return -EBADMSG;
321 322 323

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
324
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
325
			       (jiffies +
326
				usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
327 328
		hctx->ccid3hctx_last_win_count	 = 0;
		hctx->ccid3hctx_t_last_win_count = now;
329 330

		/* Set t_0 for initial packet */
331
		hctx->ccid3hctx_t_nom = now;
332 333 334 335 336 337 338 339 340 341 342 343

		hctx->ccid3hctx_s = skb->len;

		/*
		 * Use initial RTT sample when available: recommended by erratum
		 * to RFC 4342. This implements the initialisation procedure of
		 * draft rfc3448bis, section 4.2. Remember, X is scaled by 2^6.
		 */
		if (dp->dccps_syn_rtt) {
			ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
			hctx->ccid3hctx_rtt  = dp->dccps_syn_rtt;
			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
344
			hctx->ccid3hctx_t_ld = now;
345 346 347 348 349 350 351 352
		} else {
			/* Sender does not have RTT sample: X = MSS/second */
			hctx->ccid3hctx_x = dp->dccps_mss_cache;
			hctx->ccid3hctx_x <<= 6;
		}
		ccid3_update_send_interval(hctx);

		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
353 354 355
		break;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
356
		delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
I
Ian McDonald 已提交
357
		ccid3_pr_debug("delay=%ld\n", (long)delay);
358
		/*
359
		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
360 361 362 363 364 365
		 *
		 * if (t_now > t_nom - delta)
		 *       // send the packet now
		 * else
		 *       // send the packet in (t_nom - t_now) milliseconds.
		 */
366
		if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
367
			return (u32)delay / 1000L;
368

369
		ccid3_hc_tx_update_win_count(hctx, now);
370
		break;
371
	case TFRC_SSTATE_TERM:
372
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
373
		return -EINVAL;
374 375
	}

376 377
	/* prepare to send now (add options etc.) */
	dp->dccps_hc_tx_insert_options = 1;
378
	DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
379
	hctx->ccid3hctx_idle = 0;
380 381

	/* set the nominal send time for the next following packet */
382 383
	hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
					     hctx->ccid3hctx_t_ipi);
384
	return 0;
385 386
}

387 388
static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
				    unsigned int len)
389
{
390
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
391
	struct dccp_tx_hist_entry *packet;
392

393
	BUG_ON(hctx == NULL);
394

395
	ccid3_hc_tx_update_s(hctx, len);
396

397
	packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
398
	if (unlikely(packet == NULL)) {
399
		DCCP_CRIT("packet history - out of memory!");
400 401
		return;
	}
402 403
	dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);

404
	packet->dccphtx_tstamp = ktime_to_timeval(ktime_get_real());
405 406 407
	packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;
	packet->dccphtx_rtt    = hctx->ccid3hctx_rtt;
	packet->dccphtx_sent   = 1;
408 409 410 411
}

static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
412
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
413
	struct ccid3_options_received *opt_recv;
414
	struct dccp_tx_hist_entry *packet;
415
	ktime_t now, t_hist;
416
	unsigned long t_nfb;
417
	u32 pinv, r_sample;
418

419
	BUG_ON(hctx == NULL);
420 421 422 423 424 425 426 427 428 429 430

	/* we are only interested in ACKs */
	if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
	      DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
		return;

	opt_recv = &hctx->ccid3hctx_options_received;

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
431
		/* get packet from history to look up t_recvdata */
432
		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
433
					      DCCP_SKB_CB(skb)->dccpd_ack_seq);
434
		if (unlikely(packet == NULL)) {
435
			DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "
436
				  "in history!\n",  dccp_role(sk), sk,
437
			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
438
				dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
439 440 441
			return;
		}

442
		/* Update receive rate in units of 64 * bytes/second */
443 444
		hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;
		hctx->ccid3hctx_x_recv <<= 6;
445 446 447

		/* Update loss event rate */
		pinv = opt_recv->ccid3or_loss_event_rate;
448
		if (pinv == ~0U || pinv == 0)	       /* see RFC 4342, 8.5   */
449
			hctx->ccid3hctx_p = 0;
450
		else				       /* can not exceed 100% */
451
			hctx->ccid3hctx_p = 1000000 / pinv;
452

453 454
		now = ktime_get_real();
		t_hist = timeval_to_ktime(packet->dccphtx_tstamp);
455 456
		/*
		 * Calculate new round trip sample as per [RFC 3448, 4.3] by
457
		 *	R_sample  =  (now - t_recvdata) - t_elapsed
458
		 */
459
		r_sample = dccp_sample_rtt(sk, now, &t_hist);
460

461 462
		/*
		 * Update RTT estimate by
463 464 465 466 467 468 469 470
		 * If (No feedback recv)
		 *    R = R_sample;
		 * Else
		 *    R = q * R + (1 - q) * R_sample;
		 *
		 * q is a constant, RFC 3448 recomments 0.9
		 */
		if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
471 472 473
			/*
			 * Larger Initial Windows [RFC 4342, sec. 5]
			 */
474
			hctx->ccid3hctx_rtt  = r_sample;
475
			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
476
			hctx->ccid3hctx_t_ld = now;
477

478
			ccid3_update_send_interval(hctx);
479

480
			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, "
481
				       "R_sample=%uus, X=%u\n", dccp_role(sk),
A
Andrew Morton 已提交
482
				       sk, hctx->ccid3hctx_s,
483
				       dccp_sk(sk)->dccps_mss_cache, r_sample,
484
				       (unsigned)(hctx->ccid3hctx_x >> 6));
485

486 487 488
			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
		} else {
			hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +
489
						   r_sample) / 10;
490

491 492 493 494 495 496
			/* Update sending rate (step 4 of [RFC 3448, 4.3]) */
			if (hctx->ccid3hctx_p > 0)
				hctx->ccid3hctx_x_calc =
					tfrc_calc_x(hctx->ccid3hctx_s,
						    hctx->ccid3hctx_rtt,
						    hctx->ccid3hctx_p);
497
			ccid3_hc_tx_update_x(sk);
498

499
			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "
500 501
				       "p=%u, X_calc=%u, X_recv=%u, X=%u\n",
				       dccp_role(sk),
502
				       sk, hctx->ccid3hctx_rtt, r_sample,
503 504
				       hctx->ccid3hctx_s, hctx->ccid3hctx_p,
				       hctx->ccid3hctx_x_calc,
505
				       (unsigned)(hctx->ccid3hctx_x_recv >> 6),
506
				       (unsigned)(hctx->ccid3hctx_x >> 6));
507 508 509 510 511 512
		}

		/* unschedule no feedback timer */
		sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);

		/* remove all packets older than the one acked from history */
513 514
		dccp_tx_hist_purge_older(ccid3_tx_hist,
					 &hctx->ccid3hctx_hist, packet);
515
		/*
516 517
		 * As we have calculated new ipi, delta, t_nom it is possible
		 * that we now can send a packet, so wake up dccp_wait_for_ccid
518 519
		 */
		sk->sk_write_space(sk);
520

521 522 523
		/*
		 * Update timeout interval for the nofeedback timer.
		 * We use a configuration option to increase the lower bound.
524 525
		 * This can help avoid triggering the nofeedback timer too
		 * often ('spinning') on LANs with small RTTs.
526
		 */
527
		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
528
						   CONFIG_IP_DCCP_CCID3_RTO *
529
						   (USEC_PER_SEC/1000));
530 531
		/*
		 * Schedule no feedback timer to expire in
532
		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
533
		 */
534
		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
535

536
		ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "
537 538
			       "expire in %lu jiffies (%luus)\n",
			       dccp_role(sk),
539 540 541
			       sk, usecs_to_jiffies(t_nfb), t_nfb);

		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
542
				   jiffies + usecs_to_jiffies(t_nfb));
543 544

		/* set idle flag */
545
		hctx->ccid3hctx_idle = 1;
546
		break;
547
	case TFRC_SSTATE_NO_SENT:	/* fall through */
G
Gerrit Renker 已提交
548
	case TFRC_SSTATE_TERM:		/* ignore feedback when closing */
549 550 551 552 553
		break;
	}
}

static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
554 555
				     unsigned char len, u16 idx,
				     unsigned char *value)
556 557
{
	int rc = 0;
558 559
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
560 561
	struct ccid3_options_received *opt_recv;

562
	BUG_ON(hctx == NULL);
563 564 565 566 567 568 569 570 571 572 573 574 575

	opt_recv = &hctx->ccid3hctx_options_received;

	if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
		opt_recv->ccid3or_seqno		     = dp->dccps_gsr;
		opt_recv->ccid3or_loss_event_rate    = ~0;
		opt_recv->ccid3or_loss_intervals_idx = 0;
		opt_recv->ccid3or_loss_intervals_len = 0;
		opt_recv->ccid3or_receive_rate	     = 0;
	}

	switch (option) {
	case TFRC_OPT_LOSS_EVENT_RATE:
576
		if (unlikely(len != 4)) {
577
			DCCP_WARN("%s(%p), invalid len %d "
578 579
				  "for TFRC_OPT_LOSS_EVENT_RATE\n",
				  dccp_role(sk), sk, len);
580 581
			rc = -EINVAL;
		} else {
582 583
			opt_recv->ccid3or_loss_event_rate =
						ntohl(*(__be32 *)value);
584
			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
585 586 587 588 589 590 591
				       dccp_role(sk), sk,
				       opt_recv->ccid3or_loss_event_rate);
		}
		break;
	case TFRC_OPT_LOSS_INTERVALS:
		opt_recv->ccid3or_loss_intervals_idx = idx;
		opt_recv->ccid3or_loss_intervals_len = len;
592
		ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
593 594 595 596 597
			       dccp_role(sk), sk,
			       opt_recv->ccid3or_loss_intervals_idx,
			       opt_recv->ccid3or_loss_intervals_len);
		break;
	case TFRC_OPT_RECEIVE_RATE:
598
		if (unlikely(len != 4)) {
599
			DCCP_WARN("%s(%p), invalid len %d "
600 601
				  "for TFRC_OPT_RECEIVE_RATE\n",
				  dccp_role(sk), sk, len);
602 603
			rc = -EINVAL;
		} else {
604 605
			opt_recv->ccid3or_receive_rate =
						ntohl(*(__be32 *)value);
606
			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
607 608 609 610 611 612 613 614 615
				       dccp_role(sk), sk,
				       opt_recv->ccid3or_receive_rate);
		}
		break;
	}

	return rc;
}

616
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
617
{
618
	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
619

620
	hctx->ccid3hctx_s     = 0;
621
	hctx->ccid3hctx_rtt   = 0;
622 623
	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
624

625 626
	hctx->ccid3hctx_no_feedback_timer.function =
				ccid3_hc_tx_no_feedback_timer;
627
	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
628 629 630 631 632 633 634
	init_timer(&hctx->ccid3hctx_no_feedback_timer);

	return 0;
}

static void ccid3_hc_tx_exit(struct sock *sk)
{
635
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
636 637 638 639 640 641 642

	BUG_ON(hctx == NULL);

	ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
	sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);

	/* Empty packet history */
643
	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
644 645
}

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
{
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);

	/* Listen socks doesn't have a private CCID block */
	if (sk->sk_state == DCCP_LISTEN)
		return;

	BUG_ON(hctx == NULL);

	info->tcpi_rto = hctx->ccid3hctx_t_rto;
	info->tcpi_rtt = hctx->ccid3hctx_rtt;
}

static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
				  u32 __user *optval, int __user *optlen)
{
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
	const void *val;

	/* Listen socks doesn't have a private CCID block */
	if (sk->sk_state == DCCP_LISTEN)
		return -EINVAL;

	switch (optname) {
	case DCCP_SOCKOPT_CCID_TX_INFO:
		if (len < sizeof(hctx->ccid3hctx_tfrc))
			return -EINVAL;
		len = sizeof(hctx->ccid3hctx_tfrc);
		val = &hctx->ccid3hctx_tfrc;
		break;
	default:
		return -ENOPROTOOPT;
	}

	if (put_user(len, optlen) || copy_to_user(optval, val, len))
		return -EFAULT;

	return 0;
}

687
/*
688
 *	Receiver Half-Connection Routines
689
 */
690
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
691 692 693 694 695 696 697 698 699 700 701 702
static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
{
	static char *ccid3_rx_state_names[] = {
	[TFRC_RSTATE_NO_DATA] = "NO_DATA",
	[TFRC_RSTATE_DATA]    = "DATA",
	[TFRC_RSTATE_TERM]    = "TERM",
	};

	return ccid3_rx_state_names[state];
}
#endif

703 704
static void ccid3_hc_rx_set_state(struct sock *sk,
				  enum ccid3_hc_rx_states state)
705
{
706
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
707 708 709
	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
710 711
		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
		       ccid3_rx_state_name(state));
712 713 714 715
	WARN_ON(state == oldstate);
	hcrx->ccid3hcrx_state = state;
}

716 717 718 719 720 721 722 723 724
static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len)
{
	if (unlikely(len == 0))	/* don't update on empty packets (e.g. ACKs) */
		ccid3_pr_debug("Packet payload length is 0 - not updating\n");
	else
		hcrx->ccid3hcrx_s = hcrx->ccid3hcrx_s == 0 ? len :
				    (9 * hcrx->ccid3hcrx_s + len) / 10;
}

725 726
static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
727
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
728
	struct dccp_sock *dp = dccp_sk(sk);
729
	struct dccp_rx_hist_entry *packet;
730
	ktime_t now, t_hist;
G
Gerrit Renker 已提交
731
	suseconds_t delta;
732

733
	ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
734

735
	now = ktime_get_real();
736

737 738 739 740
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
		hcrx->ccid3hcrx_x_recv = 0;
		break;
G
Gerrit Renker 已提交
741
	case TFRC_RSTATE_DATA:
742 743
		delta = ktime_us_delta(now,
				       hcrx->ccid3hcrx_tstamp_last_feedback);
G
Gerrit Renker 已提交
744
		DCCP_BUG_ON(delta < 0);
745 746
		hcrx->ccid3hcrx_x_recv =
			scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
747
		break;
748
	case TFRC_RSTATE_TERM:
749
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
750 751 752
		return;
	}

753
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
754
	if (unlikely(packet == NULL)) {
755
		DCCP_WARN("%s(%p), no data packet in history!\n",
756
			  dccp_role(sk), sk);
757 758 759
		return;
	}

760
	hcrx->ccid3hcrx_tstamp_last_feedback = now;
I
Ian McDonald 已提交
761
	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
762 763
	hcrx->ccid3hcrx_bytes_recv	     = 0;

G
Gerrit Renker 已提交
764
	/* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
765 766
	t_hist = timeval_to_ktime(packet->dccphrx_tstamp);
	delta = ktime_us_delta(now, t_hist);
G
Gerrit Renker 已提交
767 768
	DCCP_BUG_ON(delta < 0);
	hcrx->ccid3hcrx_elapsed_time = delta / 10;
769

770
	if (hcrx->ccid3hcrx_p == 0)
771 772 773 774 775
		hcrx->ccid3hcrx_pinv = ~0U;	/* see RFC 4342, 8.5 */
	else if (hcrx->ccid3hcrx_p > 1000000) {
		DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p);
		hcrx->ccid3hcrx_pinv = 1;	/* use 100% in this case */
	} else
776
		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
777

778
	dp->dccps_hc_rx_insert_options = 1;
779 780 781
	dccp_send_ack(sk);
}

782
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
783
{
784
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
785
	__be32 x_recv, pinv;
786

787 788 789
	BUG_ON(hcrx == NULL);

	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
790
		return 0;
791

I
Ian McDonald 已提交
792
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
793 794

	if (dccp_packet_without_ack(skb))
795 796
		return 0;

797 798
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
799 800 801 802 803 804

	if ((hcrx->ccid3hcrx_elapsed_time != 0 &&
	     dccp_insert_option_elapsed_time(sk, skb,
					     hcrx->ccid3hcrx_elapsed_time)) ||
	    dccp_insert_option_timestamp(sk, skb) ||
	    dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
805
			       &pinv, sizeof(pinv)) ||
806
	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
807
			       &x_recv, sizeof(x_recv)))
808 809 810
		return -1;

	return 0;
811 812
}

I
Ian McDonald 已提交
813
static int ccid3_hc_rx_detect_loss(struct sock *sk,
814
				    struct dccp_rx_hist_entry *packet)
815
{
816
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
817 818
	struct dccp_rx_hist_entry *rx_hist =
				dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
I
Ian McDonald 已提交
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
	u64 seqno = packet->dccphrx_seqno;
	u64 tmp_seqno;
	int loss = 0;
	u8 ccval;


	tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;

	if (!rx_hist ||
	   follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
		hcrx->ccid3hcrx_seqno_nonloss = seqno;
		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
		goto detect_out;
	}

834

I
Ian McDonald 已提交
835 836
	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
	   > TFRC_RECV_NUM_LATE_LOSS) {
837 838
		struct timeval tstamp =
			ktime_to_timeval(hcrx->ccid3hcrx_tstamp_last_feedback);
I
Ian McDonald 已提交
839
		loss = 1;
840
		dccp_li_update_li(sk,
841 842
				  &hcrx->ccid3hcrx_li_hist,
				  &hcrx->ccid3hcrx_hist,
843
				  &tstamp,
844 845 846 847 848
				  hcrx->ccid3hcrx_s,
				  hcrx->ccid3hcrx_bytes_recv,
				  hcrx->ccid3hcrx_x_recv,
				  hcrx->ccid3hcrx_seqno_nonloss,
				  hcrx->ccid3hcrx_ccval_nonloss);
I
Ian McDonald 已提交
849 850 851 852 853 854
		tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
		dccp_inc_seqno(&tmp_seqno);
		hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
		dccp_inc_seqno(&tmp_seqno);
		while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
		   tmp_seqno, &ccval)) {
855
			hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
I
Ian McDonald 已提交
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
			hcrx->ccid3hcrx_ccval_nonloss = ccval;
			dccp_inc_seqno(&tmp_seqno);
		}
	}

	/* FIXME - this code could be simplified with above while */
	/* but works at moment */
	if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
		hcrx->ccid3hcrx_seqno_nonloss = seqno;
		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
	}

detect_out:
	dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
		   &hcrx->ccid3hcrx_li_hist, packet,
		   hcrx->ccid3hcrx_seqno_nonloss);
	return loss;
873 874 875 876
}

static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
877
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
878
	const struct dccp_options_received *opt_recv;
879
	struct dccp_rx_hist_entry *packet;
880
	u32 p_prev, r_sample, rtt_prev;
881
	int loss, payload_size;
882
	ktime_t now;
883

884
	BUG_ON(hcrx == NULL);
885

886
	opt_recv = &dccp_sk(sk)->dccps_options_received;
887

888 889 890 891
	switch (DCCP_SKB_CB(skb)->dccpd_type) {
	case DCCP_PKT_ACK:
		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			return;
892
	case DCCP_PKT_DATAACK:
893
		if (opt_recv->dccpor_timestamp_echo == 0)
894
			break;
I
Ian McDonald 已提交
895
		rtt_prev = hcrx->ccid3hcrx_rtt;
896 897
		now = ktime_get_real();
		r_sample = dccp_sample_rtt(sk, now, NULL);
898 899 900 901 902 903 904

		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			hcrx->ccid3hcrx_rtt = r_sample;
		else
			hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
					      r_sample / 10;

I
Ian McDonald 已提交
905
		if (rtt_prev != hcrx->ccid3hcrx_rtt)
906 907
			ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
				       dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
908
				       opt_recv->dccpor_elapsed_time);
909 910 911
		break;
	case DCCP_PKT_DATA:
		break;
912
	default: /* We're not interested in other packet types, move along */
913 914 915
		return;
	}

916
	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
917
					skb, GFP_ATOMIC);
918
	if (unlikely(packet == NULL)) {
919
		DCCP_WARN("%s(%p), Not enough mem to add rx packet "
920
			  "to history, consider it lost!\n", dccp_role(sk), sk);
921 922 923
		return;
	}

I
Ian McDonald 已提交
924
	loss = ccid3_hc_rx_detect_loss(sk, packet);
925 926 927 928

	if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
		return;

929 930 931
	payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;
	ccid3_hc_rx_update_s(hcrx, payload_size);

932 933
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
934 935
		ccid3_pr_debug("%s(%p, state=%s), skb=%p, sending initial "
			       "feedback\n", dccp_role(sk), sk,
936
			       dccp_state_name(sk->sk_state), skb);
937 938 939
		ccid3_hc_rx_send_feedback(sk);
		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
		return;
940
	case TFRC_RSTATE_DATA:
941
		hcrx->ccid3hcrx_bytes_recv += payload_size;
I
Ian McDonald 已提交
942
		if (loss)
943 944
			break;

945 946 947
		now = ktime_get_real();
		if ((ktime_us_delta(now, hcrx->ccid3hcrx_tstamp_last_ack) -
		     (s64)hcrx->ccid3hcrx_rtt) >= 0) {
948 949
			hcrx->ccid3hcrx_tstamp_last_ack = now;
			ccid3_hc_rx_send_feedback(sk);
950
		}
951
		return;
952
	case TFRC_RSTATE_TERM:
953
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
954 955 956 957
		return;
	}

	/* Dealing with packet loss */
958
	ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
959
		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
960 961

	p_prev = hcrx->ccid3hcrx_p;
962

963
	/* Calculate loss event rate */
I
Ian McDonald 已提交
964 965 966
	if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
		u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);

967
		/* Scaling up by 1000000 as fixed decimal */
I
Ian McDonald 已提交
968 969
		if (i_mean != 0)
			hcrx->ccid3hcrx_p = 1000000 / i_mean;
970 971
	} else
		DCCP_BUG("empty loss history");
972 973 974 975 976 977 978

	if (hcrx->ccid3hcrx_p > p_prev) {
		ccid3_hc_rx_send_feedback(sk);
		return;
	}
}

979
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
980
{
981
	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
982

983
	ccid3_pr_debug("entry\n");
984 985 986

	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
987
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
988
	hcrx->ccid3hcrx_tstamp_last_feedback =
989
		hcrx->ccid3hcrx_tstamp_last_ack = ktime_get_real();
990
	hcrx->ccid3hcrx_s   = 0;
991
	hcrx->ccid3hcrx_rtt = 0;
992 993 994 995 996
	return 0;
}

static void ccid3_hc_rx_exit(struct sock *sk)
{
997
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
998

999
	BUG_ON(hcrx == NULL);
1000 1001 1002 1003

	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);

	/* Empty packet history */
1004
	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
1005 1006

	/* Empty loss interval history */
1007
	dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
1008 1009
}

1010 1011
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
{
1012
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1013

1014 1015 1016 1017
	/* Listen socks doesn't have a private CCID block */
	if (sk->sk_state == DCCP_LISTEN)
		return;

1018
	BUG_ON(hcrx == NULL);
1019

1020 1021 1022
	info->tcpi_ca_state = hcrx->ccid3hcrx_state;
	info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;
	info->tcpi_rcv_rtt  = hcrx->ccid3hcrx_rtt;
1023 1024
}

1025 1026 1027 1028 1029
static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
				  u32 __user *optval, int __user *optlen)
{
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
	const void *val;
1030

1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
	/* Listen socks doesn't have a private CCID block */
	if (sk->sk_state == DCCP_LISTEN)
		return -EINVAL;

	switch (optname) {
	case DCCP_SOCKOPT_CCID_RX_INFO:
		if (len < sizeof(hcrx->ccid3hcrx_tfrc))
			return -EINVAL;
		len = sizeof(hcrx->ccid3hcrx_tfrc);
		val = &hcrx->ccid3hcrx_tfrc;
		break;
	default:
		return -ENOPROTOOPT;
	}

	if (put_user(len, optlen) || copy_to_user(optval, val, len))
		return -EFAULT;

	return 0;
}

1052
static struct ccid_operations ccid3 = {
I
Ian McDonald 已提交
1053
	.ccid_id		   = DCCPC_CCID3,
1054 1055
	.ccid_name		   = "ccid3",
	.ccid_owner		   = THIS_MODULE,
1056
	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),
1057 1058 1059 1060 1061 1062
	.ccid_hc_tx_init	   = ccid3_hc_tx_init,
	.ccid_hc_tx_exit	   = ccid3_hc_tx_exit,
	.ccid_hc_tx_send_packet	   = ccid3_hc_tx_send_packet,
	.ccid_hc_tx_packet_sent	   = ccid3_hc_tx_packet_sent,
	.ccid_hc_tx_packet_recv	   = ccid3_hc_tx_packet_recv,
	.ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,
1063
	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
1064 1065 1066 1067
	.ccid_hc_rx_init	   = ccid3_hc_rx_init,
	.ccid_hc_rx_exit	   = ccid3_hc_rx_exit,
	.ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
	.ccid_hc_rx_packet_recv	   = ccid3_hc_rx_packet_recv,
1068 1069
	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
1070 1071
	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
1072
};
1073

1074
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
1075 1076
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
1077
#endif
1078 1079 1080

static __init int ccid3_module_init(void)
{
1081
	int rc = -ENOBUFS;
1082

1083 1084
	ccid3_rx_hist = dccp_rx_hist_new("ccid3");
	if (ccid3_rx_hist == NULL)
1085 1086
		goto out;

1087 1088 1089
	ccid3_tx_hist = dccp_tx_hist_new("ccid3");
	if (ccid3_tx_hist == NULL)
		goto out_free_rx;
1090 1091

	rc = ccid_register(&ccid3);
1092
	if (rc != 0)
1093
		goto out_free_tx;
1094 1095
out:
	return rc;
1096 1097 1098 1099 1100 1101 1102

out_free_tx:
	dccp_tx_hist_delete(ccid3_tx_hist);
	ccid3_tx_hist = NULL;
out_free_rx:
	dccp_rx_hist_delete(ccid3_rx_hist);
	ccid3_rx_hist = NULL;
1103 1104 1105 1106 1107 1108 1109 1110
	goto out;
}
module_init(ccid3_module_init);

static __exit void ccid3_module_exit(void)
{
	ccid_unregister(&ccid3);

1111 1112 1113
	if (ccid3_tx_hist != NULL) {
		dccp_tx_hist_delete(ccid3_tx_hist);
		ccid3_tx_hist = NULL;
1114
	}
1115 1116 1117
	if (ccid3_rx_hist != NULL) {
		dccp_rx_hist_delete(ccid3_rx_hist);
		ccid3_rx_hist = NULL;
1118 1119 1120 1121
	}
}
module_exit(ccid3_module_exit);

1122
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1123
	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1124 1125 1126
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
MODULE_ALIAS("net-dccp-ccid-3");