ccid3.c 35.3 KB
Newer Older
1 2 3 4
/*
 *  net/dccp/ccids/ccid3.c
 *
 *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
5
 *  Copyright (c) 2005-6 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 38
 *
 *  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"
39
#include "lib/packet_history.h"
40
#include "lib/loss_interval.h"
41
#include "lib/tfrc.h"
42 43
#include "ccid3.h"

44
/*
45 46
 * Reason for maths here is to avoid 32 bit overflow when a is big.
 * With this we get close to the limit.
47
 */
48
static u32 usecs_div(const u32 a, const u32 b)
49
{
50 51 52 53 54 55 56 57 58 59 60
	const u32 div = a < (UINT_MAX / (USEC_PER_SEC /    10)) ?    10 :
			a < (UINT_MAX / (USEC_PER_SEC /    50)) ?    50 :
			a < (UINT_MAX / (USEC_PER_SEC /   100)) ?   100 :
			a < (UINT_MAX / (USEC_PER_SEC /   500)) ?   500 :
			a < (UINT_MAX / (USEC_PER_SEC /  1000)) ?  1000 :
			a < (UINT_MAX / (USEC_PER_SEC /  5000)) ?  5000 :
			a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 :
			a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 :
								 100000;
	const u32 tmp = a * (USEC_PER_SEC / div);
	return (b >= 2 * div) ? tmp / (b / div) : tmp;
61 62
}

63

64 65 66 67

#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
static int ccid3_debug;
#define ccid3_pr_debug(format, a...)	DCCP_PR_DEBUG(ccid3_debug, format, ##a)
68 69 70 71
#else
#define ccid3_pr_debug(format, a...)
#endif

72 73
static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
74
static struct dccp_li_hist *ccid3_li_hist;
75

76
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
77 78 79 80 81 82 83 84 85 86 87 88 89
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

90 91
static void ccid3_hc_tx_set_state(struct sock *sk,
				  enum ccid3_hc_tx_states state)
92
{
93
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
94 95 96
	enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
97 98
		       dccp_role(sk), sk, ccid3_tx_state_name(oldstate),
		       ccid3_tx_state_name(state));
99 100 101 102 103 104 105
	WARN_ON(state == oldstate);
	hctx->ccid3hctx_state = state;
}

/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
{
106
	hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
107 108 109 110 111
}

/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
{
112 113
	hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
					   TFRC_OPSYS_HALF_TIME_GRAN);
114 115 116 117 118 119 120 121 122 123 124 125 126 127
}

/*
 * Update X by
 *    If (p > 0)
 *       x_calc = calcX(s, R, p);
 *       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;
 */ 
static void ccid3_hc_tx_update_x(struct sock *sk)
{
128
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
129

130 131
	/* To avoid large error in calcX */
	if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
132 133 134
		hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
						     hctx->ccid3hctx_rtt,
						     hctx->ccid3hctx_p);
135 136 137 138
		hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc,
							  2 * hctx->ccid3hctx_x_recv),
					       (hctx->ccid3hctx_s /
					        TFRC_MAX_BACK_OFF_TIME));
139 140 141
	} else {
		struct timeval now;

142
		dccp_timestamp(sk, &now);
143 144
	       	if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
		    hctx->ccid3hctx_rtt) {
145 146 147 148
			hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
								  hctx->ccid3hctx_x) * 2,
						       usecs_div(hctx->ccid3hctx_s,
							       	 hctx->ccid3hctx_rtt));
149 150
			hctx->ccid3hctx_t_ld = now;
		}
151 152 153 154 155 156 157
	}
}

static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
	struct sock *sk = (struct sock *)data;
	unsigned long next_tmout = 0;
158
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
159 160 161 162 163

	bh_lock_sock(sk);
	if (sock_owned_by_user(sk)) {
		/* Try again later. */
		/* XXX: set some sensible MIB */
164 165
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
			       jiffies + HZ / 5);
166 167 168 169 170 171 172 173 174 175
		goto out;
	}

	ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
		       ccid3_tx_state_name(hctx->ccid3hctx_state));
	
	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_FBACK:
		/* Halve send rate */
		hctx->ccid3hctx_x /= 2;
176 177
		if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
					 TFRC_MAX_BACK_OFF_TIME))
178 179
			hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
					     TFRC_MAX_BACK_OFF_TIME);
180

181 182 183 184
		ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
			       "bytes/s\n",
			       dccp_role(sk), sk,
			       ccid3_tx_state_name(hctx->ccid3hctx_state),
185
			       hctx->ccid3hctx_x);
186 187
		next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
						      hctx->ccid3hctx_x),
188 189 190 191 192 193
					TFRC_INITIAL_TIMEOUT);
		/*
		 * FIXME - not sure above calculation is correct. See section
		 * 5 of CCID3 11 should adjust tx_t_ipi and double that to
		 * achieve it really
		 */
194 195
		break;
	case TFRC_SSTATE_FBACK:
196 197 198 199 200
		/*
		 * Check if IDLE since last timeout and recv rate is less than
		 * 4 packets per RTT
		 */
		if (!hctx->ccid3hctx_idle ||
201 202
		    (hctx->ccid3hctx_x_recv >=
		     4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
203 204
			ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
				       dccp_role(sk), sk,
205 206 207 208 209 210 211 212
				       ccid3_tx_state_name(hctx->ccid3hctx_state));
			/* Halve sending rate */

			/*  If (X_calc > 2 * X_recv)
			 *    X_recv = max(X_recv / 2, s / (2 * t_mbi));
			 *  Else
			 *    X_recv = X_calc / 4;
			 */
213 214
			BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P &&
			       hctx->ccid3hctx_x_calc == 0);
215 216 217 218 219 220 221 222 223 224 225 226

			/* check also if p is zero -> x_calc is infinity? */
			if (hctx->ccid3hctx_p < TFRC_SMALLEST_P ||
			    hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
				hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
								    hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME));
			else
				hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;

			/* Update sending rate */
			ccid3_hc_tx_update_x(sk);
		}
227 228 229 230
		/*
		 * Schedule no feedback timer to expire in
		 * max(4 * R, 2 * s / X)
		 */
231
		next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, 
232 233
					2 * usecs_div(hctx->ccid3hctx_s,
						      hctx->ccid3hctx_x));
234
		break;
235 236 237 238
	case TFRC_SSTATE_NO_SENT:
		DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
		/* fall through */
	case TFRC_SSTATE_TERM:
239 240 241 242
		goto out;
	}

	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
243
		      jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
244 245 246 247 248 249
	hctx->ccid3hctx_idle = 1;
out:
	bh_unlock_sock(sk);
	sock_put(sk);
}

250 251 252 253 254 255
/*
 * returns
 *   > 0: delay (in msecs) that should pass before actually sending
 *   = 0: can send immediately
 *   < 0: error condition; do not send packet
 */
256 257
static int ccid3_hc_tx_send_packet(struct sock *sk,
				   struct sk_buff *skb, int len)
258 259
{
	struct dccp_sock *dp = dccp_sk(sk);
260
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
261
	struct dccp_tx_hist_entry *new_packet;
262
	struct timeval now;
263
	long delay;
264

265
	BUG_ON(hctx == NULL);
266

267
	/*
268 269 270
	 * 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.
271
	 */
272
	if (unlikely(len == 0))
273
		return -EBADMSG;
274 275

	/* See if last packet allocated was not sent */
276 277
	new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
	if (new_packet == NULL || new_packet->dccphtx_sent) {
278 279
		new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
						    SLAB_ATOMIC);
280

281
		if (unlikely(new_packet == NULL)) {
282 283
			DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
				  "send refused\n", dccp_role(sk), sk);
284
			return -ENOBUFS;
285 286
		}

287
		dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
288 289
	}

290
	dccp_timestamp(sk, &now);
291 292 293

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
294 295
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
			       jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
296 297 298 299
		hctx->ccid3hctx_last_win_count	 = 0;
		hctx->ccid3hctx_t_last_win_count = now;
		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);

300 301 302 303 304 305
		/* First timeout, according to [RFC 3448, 4.2], is 1 second */
		hctx->ccid3hctx_t_ipi = USEC_PER_SEC;
		/* Initial delta: minimum of 0.5 sec and t_gran/2 */
		hctx->ccid3hctx_delta = TFRC_OPSYS_HALF_TIME_GRAN;

		/* Set t_0 for initial packet */
306 307 308 309
		hctx->ccid3hctx_t_nom = now;
		break;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
310 311 312 313 314 315 316 317 318
		delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
		/*
		 * 	Scheduling of packet transmissions [RFC 3448, 4.6]
		 *
		 * if (t_now > t_nom - delta)
		 *       // send the packet now
		 * else
		 *       // send the packet in (t_nom - t_now) milliseconds.
		 */
319 320
		if (delay >= hctx->ccid3hctx_delta)
			return delay / 1000L;
321
		break;
322 323
	case TFRC_SSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
324
		return -EINVAL;
325 326
	}

327 328 329 330 331 332 333
	/* prepare to send now (add options etc.) */
	dp->dccps_hc_tx_insert_options = 1;
	new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval =
				    hctx->ccid3hctx_last_win_count;
	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);

	return 0;
334 335 336 337
}

static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
{
338 339
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
340 341
	struct timeval now;

342
	BUG_ON(hctx == NULL);
343

344
	dccp_timestamp(sk, &now);
345 346 347 348

	/* check if we have sent a data packet */
	if (len > 0) {
		unsigned long quarter_rtt;
349
		struct dccp_tx_hist_entry *packet;
350

351
		packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
352
		if (unlikely(packet == NULL)) {
353
			DCCP_WARN("packet doesn't exist in history!\n");
354 355
			return;
		}
356
		if (unlikely(packet->dccphtx_sent)) {
357
			DCCP_WARN("no unsent packet in history!\n");
358 359
			return;
		}
360 361
		packet->dccphtx_tstamp = now;
		packet->dccphtx_seqno  = dp->dccps_gss;
362
		/*
363
		 * Check if win_count have changed
364
		 * Algorithm in "8.1. Window Counter Value" in RFC 4342.
365
		 */
366 367 368 369
		quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
		if (likely(hctx->ccid3hctx_rtt > 8))
			quarter_rtt /= hctx->ccid3hctx_rtt / 4;

370 371 372 373
		if (quarter_rtt > 0) {
			hctx->ccid3hctx_t_last_win_count = now;
			hctx->ccid3hctx_last_win_count	 = (hctx->ccid3hctx_last_win_count +
							    min_t(unsigned long, quarter_rtt, 5)) % 16;
374 375
			ccid3_pr_debug("%s, sk=%p, window changed from "
				       "%u to %u!\n",
376
				       dccp_role(sk), sk,
377
				       packet->dccphtx_ccval,
378 379
				       hctx->ccid3hctx_last_win_count);
		}
380

381
		hctx->ccid3hctx_idle = 0;
382
		packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
383
		packet->dccphtx_sent = 1;
384 385 386 387 388 389 390
	} else
		ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
			       dccp_role(sk), sk, dp->dccps_gss);
}

static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
391 392
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
393
	struct ccid3_options_received *opt_recv;
394
	struct dccp_tx_hist_entry *packet;
395
	struct timeval now;
396
	unsigned long next_tmout; 
I
Ian McDonald 已提交
397
	u32 t_elapsed;
398 399 400
	u32 pinv;
	u32 x_recv;
	u32 r_sample;
401

402
	BUG_ON(hctx == NULL);
403 404 405 406 407 408 409 410

	/* 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;

411
	t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
412 413 414 415 416 417 418 419 420 421 422 423
	x_recv = opt_recv->ccid3or_receive_rate;
	pinv = opt_recv->ccid3or_loss_event_rate;

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
		/* FIXME: what to do here? */
		return;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
		/* Calculate new round trip sample by
		 * R_sample = (now - t_recvdata) - t_delay */
		/* get t_recvdata from history */
424 425
		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
						 DCCP_SKB_CB(skb)->dccpd_ack_seq);
426
		if (unlikely(packet == NULL)) {
427 428
			DCCP_WARN("%s, sk=%p, seqno %llu(%s) does't exist "
				  "in history!\n",  dccp_role(sk), sk,
429
			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
430
				  dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
431 432 433 434
			return;
		}

		/* Update RTT */
435 436
		dccp_timestamp(sk, &now);
		r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
437
		if (unlikely(r_sample <= t_elapsed))
438 439
			DCCP_WARN("r_sample=%uus,t_elapsed=%uus\n",
				  r_sample, t_elapsed);
440 441
		else
			r_sample -= t_elapsed;
442 443 444 445 446 447 448 449 450 451 452 453 454

		/* Update RTT estimate by 
		 * 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) {
			ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
			hctx->ccid3hctx_rtt = r_sample;
		} else
455 456
			hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
					      r_sample / 10;
457

458 459 460
		ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
			       "r_sample=%us\n", dccp_role(sk), sk,
			       hctx->ccid3hctx_rtt, r_sample);
461 462

		/* Update timeout interval */
463 464
		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
					      USEC_PER_SEC);
465 466

		/* Update receive rate */
467
		hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */
468 469 470 471 472 473 474 475 476

		/* Update loss event rate */
		if (pinv == ~0 || pinv == 0)
			hctx->ccid3hctx_p = 0;
		else {
			hctx->ccid3hctx_p = 1000000 / pinv;

			if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) {
				hctx->ccid3hctx_p = TFRC_SMALLEST_P;
477 478
				ccid3_pr_debug("%s, sk=%p, Smallest p used!\n",
					       dccp_role(sk), sk);
479 480 481 482 483 484 485 486 487 488
			}
		}

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

		/* Update sending rate */
		ccid3_hc_tx_update_x(sk);

		/* Update next send time */
489 490
		timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
491
		ccid3_calc_new_t_ipi(hctx);
492 493
		timeval_add_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
494 495 496
		ccid3_calc_new_delta(hctx);

		/* remove all packets older than the one acked from history */
497 498
		dccp_tx_hist_purge_older(ccid3_tx_hist,
					 &hctx->ccid3hctx_hist, packet);
499 500 501 502 503
		/*
		 * 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_ccids.
		 */
		sk->sk_write_space(sk);
504

505 506 507 508
		/*
		 * Schedule no feedback timer to expire in
		 * max(4 * R, 2 * s / X)
		 */
509
		next_tmout = max(hctx->ccid3hctx_t_rto,
510 511 512
				 2 * usecs_div(hctx->ccid3hctx_s,
					       hctx->ccid3hctx_x));
			
513 514 515 516
		ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
			       "expire in %lu jiffies (%luus)\n",
			       dccp_role(sk), sk,
			       usecs_to_jiffies(next_tmout), next_tmout); 
517 518

		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
519
			       jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
520 521 522 523

		/* set idle flag */
		hctx->ccid3hctx_idle = 1;   
		break;
524 525
	case TFRC_SSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
526 527 528 529
		break;
	}
}

530
static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
531
{
532
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
533

534 535
	BUG_ON(hctx == NULL);

536 537 538
	if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
		DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
	return 0;
539 540 541
}

static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
542 543
				     unsigned char len, u16 idx,
				     unsigned char *value)
544 545
{
	int rc = 0;
546 547
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
548 549
	struct ccid3_options_received *opt_recv;

550
	BUG_ON(hctx == NULL);
551 552 553 554 555 556 557 558 559 560 561 562 563

	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:
564
		if (unlikely(len != 4)) {
565 566 567
			DCCP_WARN("%s, sk=%p, invalid len %d "
				  "for TFRC_OPT_LOSS_EVENT_RATE\n",
				  dccp_role(sk), sk, len);
568 569
			rc = -EINVAL;
		} else {
570
			opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
571 572 573 574 575 576 577 578 579 580 581 582 583 584
			ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
				       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;
		ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
			       dccp_role(sk), sk,
			       opt_recv->ccid3or_loss_intervals_idx,
			       opt_recv->ccid3or_loss_intervals_len);
		break;
	case TFRC_OPT_RECEIVE_RATE:
585
		if (unlikely(len != 4)) {
586 587 588
			DCCP_WARN("%s, sk=%p, invalid len %d "
				  "for TFRC_OPT_RECEIVE_RATE\n",
				  dccp_role(sk), sk, len);
589 590
			rc = -EINVAL;
		} else {
591
			opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
592 593 594 595 596 597 598 599 600 601
			ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
				       dccp_role(sk), sk,
				       opt_recv->ccid3or_receive_rate);
		}
		break;
	}

	return rc;
}

602
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
603 604
{
	struct dccp_sock *dp = dccp_sk(sk);
605
	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
606

607 608 609
	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
		hctx->ccid3hctx_s = dp->dccps_packet_size;
610 611 612
	else
		hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;

613 614
	/* Set transmission rate to 1 packet per second */
	hctx->ccid3hctx_x     = hctx->ccid3hctx_s;
615
	hctx->ccid3hctx_t_rto = USEC_PER_SEC;
616 617
	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
618 619 620

	hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
621 622 623 624 625 626 627
	init_timer(&hctx->ccid3hctx_no_feedback_timer);

	return 0;
}

static void ccid3_hc_tx_exit(struct sock *sk)
{
628
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
629 630 631 632 633 634 635

	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 */
636
	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
637 638 639 640 641 642
}

/*
 * RX Half Connection methods
 */

643
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
644 645 646 647 648 649 650 651 652 653 654 655
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

656 657
static void ccid3_hc_rx_set_state(struct sock *sk,
				  enum ccid3_hc_rx_states state)
658
{
659
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
660 661 662
	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
663 664
		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
		       ccid3_rx_state_name(state));
665 666 667 668 669 670
	WARN_ON(state == oldstate);
	hcrx->ccid3hcrx_state = state;
}

static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
671
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
672
	struct dccp_sock *dp = dccp_sk(sk);
673
	struct dccp_rx_hist_entry *packet;
674
	struct timeval now;
675 676 677

	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);

678
	dccp_timestamp(sk, &now);
679

680 681 682 683 684
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
		hcrx->ccid3hcrx_x_recv = 0;
		break;
	case TFRC_RSTATE_DATA: {
685 686
		const u32 delta = timeval_delta(&now,
					&hcrx->ccid3hcrx_tstamp_last_feedback);
687 688
		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
						   delta);
689 690
	}
		break;
691 692
	case TFRC_RSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
693 694 695
		return;
	}

696
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
697
	if (unlikely(packet == NULL)) {
698 699
		DCCP_WARN("%s, sk=%p, no data packet in history!\n",
			  dccp_role(sk), sk);
700 701 702
		return;
	}

703
	hcrx->ccid3hcrx_tstamp_last_feedback = now;
I
Ian McDonald 已提交
704
	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
705 706 707
	hcrx->ccid3hcrx_bytes_recv	     = 0;

	/* Convert to multiples of 10us */
708 709
	hcrx->ccid3hcrx_elapsed_time =
			timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
710 711 712 713
	if (hcrx->ccid3hcrx_p == 0)
		hcrx->ccid3hcrx_pinv = ~0;
	else
		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
714
	dp->dccps_hc_rx_insert_options = 1;
715 716 717
	dccp_send_ack(sk);
}

718
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
719
{
720
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
721
	__be32 x_recv, pinv;
722

723 724 725
	BUG_ON(hcrx == NULL);

	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
726
		return 0;
727

I
Ian McDonald 已提交
728
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
729 730

	if (dccp_packet_without_ack(skb))
731 732
		return 0;

733 734
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
735 736 737 738 739 740 741 742 743 744 745 746

	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,
		    	       &pinv, sizeof(pinv)) ||
	    dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
		    	       &x_recv, sizeof(x_recv)))
		return -1;

	return 0;
747 748 749 750 751 752 753 754
}

/* calculate first loss interval
 *
 * returns estimated loss interval in usecs */

static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
{
755
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
756
	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
757
	u32 rtt, delta, x_recv, fval, p, tmp2;
758
	struct timeval tstamp = { 0, };
759 760 761 762 763
	int interval = 0;
	int win_count = 0;
	int step = 0;
	u64 tmp1;

764 765 766
	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
				 dccphrx_node) {
		if (dccp_rx_hist_entry_data_packet(entry)) {
767 768 769 770
			tail = entry;

			switch (step) {
			case 0:
771
				tstamp	  = entry->dccphrx_tstamp;
772
				win_count = entry->dccphrx_ccval;
773 774 775
				step = 1;
				break;
			case 1:
776
				interval = win_count - entry->dccphrx_ccval;
777 778 779 780 781 782 783 784 785
				if (interval < 0)
					interval += TFRC_WIN_COUNT_LIMIT;
				if (interval > 4)
					goto found;
				break;
			}
		}
	}

786
	if (unlikely(step == 0)) {
787 788
		DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
			  dccp_role(sk), sk);
789 790 791
		return ~0;
	}

792
	if (unlikely(interval == 0)) {
793 794
		DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
			  "Defaulting to 1\n", dccp_role(sk), sk);
795 796 797
		interval = 1;
	}
found:
I
Ian McDonald 已提交
798
	if (!tail) {
799
		DCCP_CRIT("tail is null\n");
I
Ian McDonald 已提交
800 801
		return ~0;
	}
802
	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
803 804
	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
		       dccp_role(sk), sk, rtt);
805 806 807 808 809

	if (rtt == 0) {
		DCCP_WARN("RTT==0, setting to 1\n");
 		rtt = 1;
	}
810

811 812 813
	dccp_timestamp(sk, &tstamp);
	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
814

I
Ian McDonald 已提交
815 816 817
	if (x_recv == 0)
		x_recv = hcrx->ccid3hcrx_x_recv;

818 819 820
	tmp1 = (u64)x_recv * (u64)rtt;
	do_div(tmp1,10000000);
	tmp2 = (u32)tmp1;
I
Ian McDonald 已提交
821 822

	if (!tmp2) {
823
		DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
I
Ian McDonald 已提交
824 825 826
		return ~0;
	}

827 828
	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
	/* do not alter order above or you will get overflow on 32 bit */
829
	p = tfrc_calc_x_reverse_lookup(fval);
830 831
	ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
832 833 834 835 836 837 838 839 840

	if (p == 0)
		return ~0;
	else
		return 1000000 / p; 
}

static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
{
841
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
842
	struct dccp_li_hist_entry *head;
I
Ian McDonald 已提交
843
	u64 seq_temp;
844

I
Ian McDonald 已提交
845 846 847 848
	if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
		if (!dccp_li_hist_interval_new(ccid3_li_hist,
		   &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
			return;
849

850 851 852
		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
		   struct dccp_li_hist_entry, dccplih_node);
		head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
I
Ian McDonald 已提交
853 854 855 856
	} else {
		struct dccp_li_hist_entry *entry;
		struct list_head *tail;

857 858
		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
		   struct dccp_li_hist_entry, dccplih_node);
I
Ian McDonald 已提交
859 860 861 862 863 864 865 866 867 868
		/* FIXME win count check removed as was wrong */
		/* should make this check with receive history */
		/* and compare there as per section 10.2 of RFC4342 */

		/* new loss event detected */
		/* calculate last interval length */
		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
		entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC);

		if (entry == NULL) {
869
			DCCP_BUG("out of memory - can not allocate entry");
870
			return;
I
Ian McDonald 已提交
871 872 873 874 875 876 877 878 879 880 881 882 883
		}

		list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);

		tail = hcrx->ccid3hcrx_li_hist.prev;
		list_del(tail);
		kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);

		/* Create the newest interval */
		entry->dccplih_seqno = seq_loss;
		entry->dccplih_interval = seq_temp;
		entry->dccplih_win_count = win_loss;
	}
884 885
}

I
Ian McDonald 已提交
886 887
static int ccid3_hc_rx_detect_loss(struct sock *sk,
                                    struct dccp_rx_hist_entry *packet)
888
{
889
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
I
Ian McDonald 已提交
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
	struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
	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;
	}

906

I
Ian McDonald 已提交
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
	   > TFRC_RECV_NUM_LATE_LOSS) {
		loss = 1;
		ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
		   hcrx->ccid3hcrx_ccval_nonloss);
		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)) {
		   	hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
			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;
936 937 938 939
}

static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
940
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
941
	const struct dccp_options_received *opt_recv;
942
	struct dccp_rx_hist_entry *packet;
943
	struct timeval now;
I
Ian McDonald 已提交
944 945
	u32 p_prev, rtt_prev, r_sample, t_elapsed;
	int loss;
946

947
	BUG_ON(hcrx == NULL);
948

949
	opt_recv = &dccp_sk(sk)->dccps_options_received;
950

951 952 953 954 955
	switch (DCCP_SKB_CB(skb)->dccpd_type) {
	case DCCP_PKT_ACK:
		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			return;
	case DCCP_PKT_DATAACK:
956
		if (opt_recv->dccpor_timestamp_echo == 0)
957
			break;
I
Ian McDonald 已提交
958
		rtt_prev = hcrx->ccid3hcrx_rtt;
959
		dccp_timestamp(sk, &now);
960 961 962 963 964
		timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
		r_sample = timeval_usecs(&now);
		t_elapsed = opt_recv->dccpor_elapsed_time * 10;

		if (unlikely(r_sample <= t_elapsed))
965 966
			DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
				  r_sample, t_elapsed);
967 968 969 970 971 972 973 974 975
		else
			r_sample -= t_elapsed;

		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 已提交
976 977
		if (rtt_prev != hcrx->ccid3hcrx_rtt)
			ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
978 979
				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
				       opt_recv->dccpor_elapsed_time);
980 981 982
		break;
	case DCCP_PKT_DATA:
		break;
983
	default: /* We're not interested in other packet types, move along */
984 985 986
		return;
	}

987
	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
988
					skb, SLAB_ATOMIC);
989
	if (unlikely(packet == NULL)) {
990 991
		DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
			  "to history, consider it lost!\n", dccp_role(sk), sk);
992 993 994
		return;
	}

I
Ian McDonald 已提交
995
	loss = ccid3_hc_rx_detect_loss(sk, packet);
996 997 998 999 1000 1001

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

	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
1002 1003 1004 1005
		ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
			       "feedback\n",
			       dccp_role(sk), sk,
			       dccp_state_name(sk->sk_state), skb);
1006 1007 1008 1009
		ccid3_hc_rx_send_feedback(sk);
		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
		return;
	case TFRC_RSTATE_DATA:
1010 1011
		hcrx->ccid3hcrx_bytes_recv += skb->len -
					      dccp_hdr(skb)->dccph_doff * 4;
I
Ian McDonald 已提交
1012
		if (loss)
1013 1014
			break;

1015
		dccp_timestamp(sk, &now);
1016 1017 1018 1019
		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
		    hcrx->ccid3hcrx_rtt) {
			hcrx->ccid3hcrx_tstamp_last_ack = now;
			ccid3_hc_rx_send_feedback(sk);
1020
		}
1021
		return;
1022 1023
	case TFRC_RSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
1024 1025 1026 1027
		return;
	}

	/* Dealing with packet loss */
1028 1029
	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
1030 1031 1032 1033

	p_prev = hcrx->ccid3hcrx_p;
	
	/* Calculate loss event rate */
I
Ian McDonald 已提交
1034 1035 1036
	if (!list_empty(&hcrx->ccid3hcrx_li_hist)) {
		u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist);

1037
		/* Scaling up by 1000000 as fixed decimal */
I
Ian McDonald 已提交
1038 1039
		if (i_mean != 0)
			hcrx->ccid3hcrx_p = 1000000 / i_mean;
1040 1041
	} else
		DCCP_BUG("empty loss history");
1042 1043 1044 1045 1046 1047 1048

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

1049
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
1050 1051
{
	struct dccp_sock *dp = dccp_sk(sk);
1052
	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
1053 1054 1055

	ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);

1056 1057 1058
	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
		hcrx->ccid3hcrx_s = dp->dccps_packet_size;
1059 1060 1061 1062 1063
	else
		hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;

	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
1064
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
1065
	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
1066 1067
	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
1068 1069 1070 1071 1072
	return 0;
}

static void ccid3_hc_rx_exit(struct sock *sk)
{
1073
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1074

1075
	BUG_ON(hcrx == NULL);
1076 1077 1078 1079

	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);

	/* Empty packet history */
1080
	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
1081 1082

	/* Empty loss interval history */
1083
	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
1084 1085
}

1086 1087
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
{
1088
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1089

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

1094
	BUG_ON(hcrx == NULL);
1095 1096 1097 1098 1099 1100 1101 1102

	info->tcpi_ca_state	= hcrx->ccid3hcrx_state;
	info->tcpi_options	|= TCPI_OPT_TIMESTAMPS;
	info->tcpi_rcv_rtt	= hcrx->ccid3hcrx_rtt;
}

static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
{
1103
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
1104

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

1109
	BUG_ON(hctx == NULL);
1110 1111 1112 1113 1114

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

1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
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;
	
	/* 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;
}

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;
}

1169
static struct ccid_operations ccid3 = {
I
Ian McDonald 已提交
1170
	.ccid_id		   = DCCPC_CCID3,
1171 1172
	.ccid_name		   = "ccid3",
	.ccid_owner		   = THIS_MODULE,
1173
	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),
1174 1175 1176 1177 1178 1179 1180
	.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_insert_options = ccid3_hc_tx_insert_options,
	.ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,
1181
	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
1182 1183 1184 1185
	.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,
1186 1187
	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
1188 1189
	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
1190 1191
};
 
1192
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
1193 1194
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
1195
#endif
1196 1197 1198

static __init int ccid3_module_init(void)
{
1199
	int rc = -ENOBUFS;
1200

1201 1202
	ccid3_rx_hist = dccp_rx_hist_new("ccid3");
	if (ccid3_rx_hist == NULL)
1203 1204
		goto out;

1205 1206 1207
	ccid3_tx_hist = dccp_tx_hist_new("ccid3");
	if (ccid3_tx_hist == NULL)
		goto out_free_rx;
1208

1209 1210
	ccid3_li_hist = dccp_li_hist_new("ccid3");
	if (ccid3_li_hist == NULL)
1211
		goto out_free_tx;
1212 1213 1214 1215 1216 1217

	rc = ccid_register(&ccid3);
	if (rc != 0) 
		goto out_free_loss_interval_history;
out:
	return rc;
1218

1219
out_free_loss_interval_history:
1220 1221
	dccp_li_hist_delete(ccid3_li_hist);
	ccid3_li_hist = NULL;
1222 1223 1224 1225 1226 1227
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;
1228 1229 1230 1231 1232 1233 1234 1235
	goto out;
}
module_init(ccid3_module_init);

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

1236 1237 1238
	if (ccid3_tx_hist != NULL) {
		dccp_tx_hist_delete(ccid3_tx_hist);
		ccid3_tx_hist = NULL;
1239
	}
1240 1241 1242
	if (ccid3_rx_hist != NULL) {
		dccp_rx_hist_delete(ccid3_rx_hist);
		ccid3_rx_hist = NULL;
1243
	}
1244 1245 1246
	if (ccid3_li_hist != NULL) {
		dccp_li_hist_delete(ccid3_li_hist);
		ccid3_li_hist = NULL;
1247 1248 1249 1250
	}
}
module_exit(ccid3_module_exit);

1251
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1252
	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1253 1254 1255
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
MODULE_ALIAS("net-dccp-ccid-3");