ccid3.c 32.3 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 132
static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)

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

G
Gerrit Renker 已提交
156
	} else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) -
157
			(suseconds_t)hctx->ccid3hctx_rtt >= 0) {
158

159
		hctx->ccid3hctx_x =
160
			max(min(2 * hctx->ccid3hctx_x, min_rate),
161
			    scaled_div(((__u64)hctx->ccid3hctx_s) << 6,
162
				       hctx->ccid3hctx_rtt));
163
		hctx->ccid3hctx_t_ld = *now;
164
	}
165

I
Ian McDonald 已提交
166
	if (hctx->ccid3hctx_x != old_x) {
167 168 169 170 171
		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 已提交
172

173
		ccid3_update_send_interval(hctx);
I
Ian McDonald 已提交
174
	}
175 176
}

177
/*
178 179
 *	Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
 *	@len: DCCP packet payload size in bytes
180 181 182
 */
static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
{
183 184 185 186 187 188
	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);
189 190
}

191
/*
192 193
 *	Update Window Counter using the algorithm from [RFC 4342, 8.1].
 *	The algorithm is not applicable if RTT < 4 microseconds.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
 */
static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
						struct timeval *now)
{
	suseconds_t delta;
	u32 quarter_rtts;

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

	delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
	DCCP_BUG_ON(delta < 0);

	quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);

	if (quarter_rtts > 0) {
		hctx->ccid3hctx_t_last_win_count = *now;
		hctx->ccid3hctx_last_win_count	+= min_t(u32, quarter_rtts, 5);
		hctx->ccid3hctx_last_win_count	&= 0xF;		/* mod 16 */

		ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
	}
}

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

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

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

235 236
	hctx->ccid3hctx_idle = 1;

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

244 245
		ccid3_pr_debug("%s(%p, state=%s), updated tx rate to %u "
			       "bytes/s\n", dccp_role(sk), sk,
246
			       ccid3_tx_state_name(hctx->ccid3hctx_state),
247
			       (unsigned)(hctx->ccid3hctx_x >> 6));
248 249
		/* The value of R is still undefined and so we can not recompute
		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
250
		t_nfb = TFRC_INITIAL_TIMEOUT;
251
		ccid3_update_send_interval(hctx);
252 253
		break;
	case TFRC_SSTATE_FBACK:
254
		/*
255 256 257 258 259 260 261 262
		 *  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
263
		 */
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
		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));

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

296 297
restart_timer:
	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
298
			   jiffies + usecs_to_jiffies(t_nfb));
299 300 301 302 303
out:
	bh_unlock_sock(sk);
	sock_put(sk);
}

304 305 306 307 308 309
/*
 * returns
 *   > 0: delay (in msecs) that should pass before actually sending
 *   = 0: can send immediately
 *   < 0: error condition; do not send packet
 */
310
static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
311 312
{
	struct dccp_sock *dp = dccp_sk(sk);
313
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
314
	struct timeval now;
G
Gerrit Renker 已提交
315
	suseconds_t delay;
316

317
	BUG_ON(hctx == NULL);
318

319
	/*
320 321 322
	 * 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.
323
	 */
324
	if (unlikely(skb->len == 0))
325
		return -EBADMSG;
326

327
	dccp_timestamp(sk, &now);
328 329 330

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
331
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
332
			       (jiffies +
333
				usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)));
334 335
		hctx->ccid3hctx_last_win_count	 = 0;
		hctx->ccid3hctx_t_last_win_count = now;
336 337

		/* Set t_0 for initial packet */
338
		hctx->ccid3hctx_t_nom = now;
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

		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);
			hctx->ccid3hctx_t_ld = now;
		} 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);
360 361 362
		break;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
363
		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
I
Ian McDonald 已提交
364
		ccid3_pr_debug("delay=%ld\n", (long)delay);
365
		/*
366
		 *	Scheduling of packet transmissions [RFC 3448, 4.6]
367 368 369 370 371 372
		 *
		 * if (t_now > t_nom - delta)
		 *       // send the packet now
		 * else
		 *       // send the packet in (t_nom - t_now) milliseconds.
		 */
G
Gerrit Renker 已提交
373
		if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
374
			return delay / 1000L;
375 376

		ccid3_hc_tx_update_win_count(hctx, &now);
377
		break;
378
	case TFRC_SSTATE_TERM:
379
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
380
		return -EINVAL;
381 382
	}

383 384
	/* prepare to send now (add options etc.) */
	dp->dccps_hc_tx_insert_options = 1;
385
	DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
386
	hctx->ccid3hctx_idle = 0;
387 388

	/* set the nominal send time for the next following packet */
389 390 391
	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);

	return 0;
392 393
}

394 395
static void ccid3_hc_tx_packet_sent(struct sock *sk, int more,
				    unsigned int len)
396
{
397
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
398
	struct timeval now;
399
	struct dccp_tx_hist_entry *packet;
400

401
	BUG_ON(hctx == NULL);
402

403
	ccid3_hc_tx_update_s(hctx, len);
404

405
	packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
406
	if (unlikely(packet == NULL)) {
407
		DCCP_CRIT("packet history - out of memory!");
408 409
		return;
	}
410 411 412
	dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);

	dccp_timestamp(sk, &now);
413
	packet->dccphtx_tstamp = now;
414 415 416
	packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;
	packet->dccphtx_rtt    = hctx->ccid3hctx_rtt;
	packet->dccphtx_sent   = 1;
417 418 419 420
}

static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
421
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
422
	struct ccid3_options_received *opt_recv;
423
	struct dccp_tx_hist_entry *packet;
424
	struct timeval now;
425
	unsigned long t_nfb;
426
	u32 pinv, r_sample;
427

428
	BUG_ON(hctx == NULL);
429 430 431 432 433 434 435 436 437 438 439

	/* 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:
440
		/* get packet from history to look up t_recvdata */
441
		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
442
					      DCCP_SKB_CB(skb)->dccpd_ack_seq);
443
		if (unlikely(packet == NULL)) {
444
			DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist "
445
				  "in history!\n",  dccp_role(sk), sk,
446
			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
447
				dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
448 449 450
			return;
		}

451
		/* Update receive rate in units of 64 * bytes/second */
452 453
		hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;
		hctx->ccid3hctx_x_recv <<= 6;
454 455 456

		/* Update loss event rate */
		pinv = opt_recv->ccid3or_loss_event_rate;
457
		if (pinv == ~0U || pinv == 0)	       /* see RFC 4342, 8.5   */
458
			hctx->ccid3hctx_p = 0;
459
		else				       /* can not exceed 100% */
460
			hctx->ccid3hctx_p = 1000000 / pinv;
461

462
		dccp_timestamp(sk, &now);
463 464 465

		/*
		 * Calculate new round trip sample as per [RFC 3448, 4.3] by
466
		 *	R_sample  =  (now - t_recvdata) - t_elapsed
467
		 */
468
		r_sample = dccp_sample_rtt(sk, &now, &packet->dccphtx_tstamp);
469

470 471
		/*
		 * Update RTT estimate by
472 473 474 475 476 477 478 479
		 * 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) {
480 481 482
			/*
			 * Larger Initial Windows [RFC 4342, sec. 5]
			 */
483
			hctx->ccid3hctx_rtt  = r_sample;
484
			hctx->ccid3hctx_x    = rfc3390_initial_rate(sk);
485 486
			hctx->ccid3hctx_t_ld = now;

487
			ccid3_update_send_interval(hctx);
488

489
			ccid3_pr_debug("%s(%p), s=%u, MSS=%u, "
490
				       "R_sample=%uus, X=%u\n", dccp_role(sk),
A
Andrew Morton 已提交
491
				       sk, hctx->ccid3hctx_s,
492
				       dccp_sk(sk)->dccps_mss_cache, r_sample,
493
				       (unsigned)(hctx->ccid3hctx_x >> 6));
494

495 496 497
			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
		} else {
			hctx->ccid3hctx_rtt = (9 * hctx->ccid3hctx_rtt +
498
						   r_sample) / 10;
499

500 501 502 503 504 505
			/* 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);
506
			ccid3_hc_tx_update_x(sk, &now);
507

508
			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%uus), s=%u, "
509 510
				       "p=%u, X_calc=%u, X_recv=%u, X=%u\n",
				       dccp_role(sk),
511
				       sk, hctx->ccid3hctx_rtt, r_sample,
512 513
				       hctx->ccid3hctx_s, hctx->ccid3hctx_p,
				       hctx->ccid3hctx_x_calc,
514
				       (unsigned)(hctx->ccid3hctx_x_recv >> 6),
515
				       (unsigned)(hctx->ccid3hctx_x >> 6));
516 517 518 519 520 521
		}

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

		/* remove all packets older than the one acked from history */
522 523
		dccp_tx_hist_purge_older(ccid3_tx_hist,
					 &hctx->ccid3hctx_hist, packet);
524
		/*
525 526
		 * 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
527 528
		 */
		sk->sk_write_space(sk);
529

530 531 532
		/*
		 * Update timeout interval for the nofeedback timer.
		 * We use a configuration option to increase the lower bound.
533 534
		 * This can help avoid triggering the nofeedback timer too
		 * often ('spinning') on LANs with small RTTs.
535
		 */
536
		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
537
						   CONFIG_IP_DCCP_CCID3_RTO *
538
						   (USEC_PER_SEC/1000));
539 540
		/*
		 * Schedule no feedback timer to expire in
541
		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
542
		 */
543
		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
544

545
		ccid3_pr_debug("%s(%p), Scheduled no feedback timer to "
546 547
			       "expire in %lu jiffies (%luus)\n",
			       dccp_role(sk),
548 549 550
			       sk, usecs_to_jiffies(t_nfb), t_nfb);

		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
551
				   jiffies + usecs_to_jiffies(t_nfb));
552 553

		/* set idle flag */
554
		hctx->ccid3hctx_idle = 1;
555
		break;
556
	case TFRC_SSTATE_NO_SENT:	/* fall through */
G
Gerrit Renker 已提交
557
	case TFRC_SSTATE_TERM:		/* ignore feedback when closing */
558 559 560 561 562
		break;
	}
}

static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
563 564
				     unsigned char len, u16 idx,
				     unsigned char *value)
565 566
{
	int rc = 0;
567 568
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
569 570
	struct ccid3_options_received *opt_recv;

571
	BUG_ON(hctx == NULL);
572 573 574 575 576 577 578 579 580 581 582 583 584

	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:
585
		if (unlikely(len != 4)) {
586
			DCCP_WARN("%s(%p), invalid len %d "
587 588
				  "for TFRC_OPT_LOSS_EVENT_RATE\n",
				  dccp_role(sk), sk, len);
589 590
			rc = -EINVAL;
		} else {
591 592
			opt_recv->ccid3or_loss_event_rate =
						ntohl(*(__be32 *)value);
593
			ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n",
594 595 596 597 598 599 600
				       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;
601
		ccid3_pr_debug("%s(%p), LOSS_INTERVALS=(%u, %u)\n",
602 603 604 605 606
			       dccp_role(sk), sk,
			       opt_recv->ccid3or_loss_intervals_idx,
			       opt_recv->ccid3or_loss_intervals_len);
		break;
	case TFRC_OPT_RECEIVE_RATE:
607
		if (unlikely(len != 4)) {
608
			DCCP_WARN("%s(%p), invalid len %d "
609 610
				  "for TFRC_OPT_RECEIVE_RATE\n",
				  dccp_role(sk), sk, len);
611 612
			rc = -EINVAL;
		} else {
613 614
			opt_recv->ccid3or_receive_rate =
						ntohl(*(__be32 *)value);
615
			ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n",
616 617 618 619 620 621 622 623 624
				       dccp_role(sk), sk,
				       opt_recv->ccid3or_receive_rate);
		}
		break;
	}

	return rc;
}

625
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
626
{
627
	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
628

629
	hctx->ccid3hctx_s     = 0;
630
	hctx->ccid3hctx_rtt   = 0;
631 632
	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
633

634 635
	hctx->ccid3hctx_no_feedback_timer.function =
				ccid3_hc_tx_no_feedback_timer;
636
	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
637 638 639 640 641 642 643
	init_timer(&hctx->ccid3hctx_no_feedback_timer);

	return 0;
}

static void ccid3_hc_tx_exit(struct sock *sk)
{
644
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
645 646 647 648 649 650 651

	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 */
652
	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
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 687 688 689 690 691 692 693 694 695
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;
}

696
/*
697
 *	Receiver Half-Connection Routines
698
 */
699
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
700 701 702 703 704 705 706 707 708 709 710 711
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

712 713
static void ccid3_hc_rx_set_state(struct sock *sk,
				  enum ccid3_hc_rx_states state)
714
{
715
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
716 717 718
	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
719 720
		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
		       ccid3_rx_state_name(state));
721 722 723 724
	WARN_ON(state == oldstate);
	hcrx->ccid3hcrx_state = state;
}

725 726 727 728 729 730 731 732 733
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;
}

734 735
static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
736
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
737
	struct dccp_sock *dp = dccp_sk(sk);
738
	struct dccp_rx_hist_entry *packet;
739
	struct timeval now;
G
Gerrit Renker 已提交
740
	suseconds_t delta;
741

742
	ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
743

744
	dccp_timestamp(sk, &now);
745

746 747 748 749
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
		hcrx->ccid3hcrx_x_recv = 0;
		break;
G
Gerrit Renker 已提交
750 751 752 753
	case TFRC_RSTATE_DATA:
		delta = timeval_delta(&now,
				      &hcrx->ccid3hcrx_tstamp_last_feedback);
		DCCP_BUG_ON(delta < 0);
754 755
		hcrx->ccid3hcrx_x_recv =
			scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
756
		break;
757
	case TFRC_RSTATE_TERM:
758
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
759 760 761
		return;
	}

762
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
763
	if (unlikely(packet == NULL)) {
764
		DCCP_WARN("%s(%p), no data packet in history!\n",
765
			  dccp_role(sk), sk);
766 767 768
		return;
	}

769
	hcrx->ccid3hcrx_tstamp_last_feedback = now;
I
Ian McDonald 已提交
770
	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
771 772
	hcrx->ccid3hcrx_bytes_recv	     = 0;

G
Gerrit Renker 已提交
773 774 775 776
	/* Elapsed time information [RFC 4340, 13.2] in units of 10 * usecs */
	delta = timeval_delta(&now, &packet->dccphrx_tstamp);
	DCCP_BUG_ON(delta < 0);
	hcrx->ccid3hcrx_elapsed_time = delta / 10;
777

778
	if (hcrx->ccid3hcrx_p == 0)
779 780 781 782 783
		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
784
		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
785

786
	dp->dccps_hc_rx_insert_options = 1;
787 788 789
	dccp_send_ack(sk);
}

790
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
791
{
792
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
793
	__be32 x_recv, pinv;
794

795 796 797
	BUG_ON(hcrx == NULL);

	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
798
		return 0;
799

I
Ian McDonald 已提交
800
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
801 802

	if (dccp_packet_without_ack(skb))
803 804
		return 0;

805 806
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
807 808 809 810 811 812

	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,
813
			       &pinv, sizeof(pinv)) ||
814
	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
815
			       &x_recv, sizeof(x_recv)))
816 817 818
		return -1;

	return 0;
819 820
}

I
Ian McDonald 已提交
821
static int ccid3_hc_rx_detect_loss(struct sock *sk,
822
				    struct dccp_rx_hist_entry *packet)
823
{
824
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
825 826
	struct dccp_rx_hist_entry *rx_hist =
				dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
I
Ian McDonald 已提交
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
	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;
	}

842

I
Ian McDonald 已提交
843 844 845
	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
	   > TFRC_RECV_NUM_LATE_LOSS) {
		loss = 1;
846
		dccp_li_update_li(sk,
847 848 849 850 851 852 853 854
				  &hcrx->ccid3hcrx_li_hist,
				  &hcrx->ccid3hcrx_hist,
				  &hcrx->ccid3hcrx_tstamp_last_feedback,
				  hcrx->ccid3hcrx_s,
				  hcrx->ccid3hcrx_bytes_recv,
				  hcrx->ccid3hcrx_x_recv,
				  hcrx->ccid3hcrx_seqno_nonloss,
				  hcrx->ccid3hcrx_ccval_nonloss);
I
Ian McDonald 已提交
855 856 857 858 859 860
		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)) {
861
			hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
I
Ian McDonald 已提交
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
			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;
879 880 881 882
}

static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
883
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
884
	const struct dccp_options_received *opt_recv;
885
	struct dccp_rx_hist_entry *packet;
886
	struct timeval now;
887
	u32 p_prev, r_sample, rtt_prev;
888
	int loss, payload_size;
889

890
	BUG_ON(hcrx == NULL);
891

892
	opt_recv = &dccp_sk(sk)->dccps_options_received;
893

894 895 896 897 898
	switch (DCCP_SKB_CB(skb)->dccpd_type) {
	case DCCP_PKT_ACK:
		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			return;
	case DCCP_PKT_DATAACK:
899
		if (opt_recv->dccpor_timestamp_echo == 0)
900
			break;
I
Ian McDonald 已提交
901
		rtt_prev = hcrx->ccid3hcrx_rtt;
902
		dccp_timestamp(sk, &now);
903
		r_sample = dccp_sample_rtt(sk, &now, NULL);
904 905 906 907 908 909 910

		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 已提交
911
		if (rtt_prev != hcrx->ccid3hcrx_rtt)
912 913
			ccid3_pr_debug("%s(%p), New RTT=%uus, elapsed time=%u\n",
				       dccp_role(sk), sk, hcrx->ccid3hcrx_rtt,
914
				       opt_recv->dccpor_elapsed_time);
915 916 917
		break;
	case DCCP_PKT_DATA:
		break;
918
	default: /* We're not interested in other packet types, move along */
919 920 921
		return;
	}

922
	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
923
					skb, GFP_ATOMIC);
924
	if (unlikely(packet == NULL)) {
925
		DCCP_WARN("%s(%p), Not enough mem to add rx packet "
926
			  "to history, consider it lost!\n", dccp_role(sk), sk);
927 928 929
		return;
	}

I
Ian McDonald 已提交
930
	loss = ccid3_hc_rx_detect_loss(sk, packet);
931 932 933 934

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

935 936 937
	payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;
	ccid3_hc_rx_update_s(hcrx, payload_size);

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

951
		dccp_timestamp(sk, &now);
952 953
		if ((timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) -
		     (suseconds_t)hcrx->ccid3hcrx_rtt) >= 0) {
954 955
			hcrx->ccid3hcrx_tstamp_last_ack = now;
			ccid3_hc_rx_send_feedback(sk);
956
		}
957
		return;
958
	case TFRC_RSTATE_TERM:
959
		DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
960 961 962 963
		return;
	}

	/* Dealing with packet loss */
964
	ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n",
965
		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
966 967

	p_prev = hcrx->ccid3hcrx_p;
968

969
	/* Calculate loss event rate */
I
Ian McDonald 已提交
970 971 972
	if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
		u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);

973
		/* Scaling up by 1000000 as fixed decimal */
I
Ian McDonald 已提交
974 975
		if (i_mean != 0)
			hcrx->ccid3hcrx_p = 1000000 / i_mean;
976 977
	} else
		DCCP_BUG("empty loss history");
978 979 980 981 982 983 984

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

985
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
986
{
987
	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
988

989
	ccid3_pr_debug("entry\n");
990 991 992

	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
993
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
994
	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
995
	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
996
	hcrx->ccid3hcrx_s   = 0;
997
	hcrx->ccid3hcrx_rtt = 0;
998 999 1000 1001 1002
	return 0;
}

static void ccid3_hc_rx_exit(struct sock *sk)
{
1003
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1004

1005
	BUG_ON(hcrx == NULL);
1006 1007 1008 1009

	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);

	/* Empty packet history */
1010
	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
1011 1012

	/* Empty loss interval history */
1013
	dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
1014 1015
}

1016 1017
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
{
1018
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1019

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

1024
	BUG_ON(hcrx == NULL);
1025

1026 1027 1028
	info->tcpi_ca_state = hcrx->ccid3hcrx_state;
	info->tcpi_options  |= TCPI_OPT_TIMESTAMPS;
	info->tcpi_rcv_rtt  = hcrx->ccid3hcrx_rtt;
1029 1030
}

1031 1032 1033 1034 1035
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;
1036

1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
	/* 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;
}

1058
static struct ccid_operations ccid3 = {
I
Ian McDonald 已提交
1059
	.ccid_id		   = DCCPC_CCID3,
1060 1061
	.ccid_name		   = "ccid3",
	.ccid_owner		   = THIS_MODULE,
1062
	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),
1063 1064 1065 1066 1067 1068
	.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,
1069
	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
1070 1071 1072 1073
	.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,
1074 1075
	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
1076 1077
	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
1078
};
1079

1080
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
1081 1082
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
1083
#endif
1084 1085 1086

static __init int ccid3_module_init(void)
{
1087
	int rc = -ENOBUFS;
1088

1089 1090
	ccid3_rx_hist = dccp_rx_hist_new("ccid3");
	if (ccid3_rx_hist == NULL)
1091 1092
		goto out;

1093 1094 1095
	ccid3_tx_hist = dccp_tx_hist_new("ccid3");
	if (ccid3_tx_hist == NULL)
		goto out_free_rx;
1096 1097

	rc = ccid_register(&ccid3);
1098
	if (rc != 0)
1099
		goto out_free_tx;
1100 1101
out:
	return rc;
1102 1103 1104 1105 1106 1107 1108

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;
1109 1110 1111 1112 1113 1114 1115 1116
	goto out;
}
module_init(ccid3_module_init);

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

1117 1118 1119
	if (ccid3_tx_hist != NULL) {
		dccp_tx_hist_delete(ccid3_tx_hist);
		ccid3_tx_hist = NULL;
1120
	}
1121 1122 1123
	if (ccid3_rx_hist != NULL) {
		dccp_rx_hist_delete(ccid3_rx_hist);
		ccid3_rx_hist = NULL;
1124 1125 1126 1127
	}
}
module_exit(ccid3_module_exit);

1128
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1129
	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1130 1131 1132
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
MODULE_ALIAS("net-dccp-ccid-3");