ccid3.c 36.5 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
	WARN_ON(state == oldstate);
	hctx->ccid3hctx_state = state;
}

103 104 105 106 107
/*
 * Recalculate scheduled nominal send time t_nom, inter-packet interval
 * t_ipi, and delta value. Should be called after each change to X.
 */
static inline void ccid3_update_send_time(struct ccid3_hc_tx_sock *hctx)
108
{
109 110 111
	timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);

	/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
112
	hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x);
113

114 115 116 117
	/* Update nominal send time with regard to the new t_ipi */
	timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);

	/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
118 119
	hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
					   TFRC_OPSYS_HALF_TIME_GRAN);
120 121 122 123
}
/*
 * Update X by
 *    If (p > 0)
124
 *       X_calc = calcX(s, R, p);
125 126 127 128 129
 *       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;
130 131 132
 *
 * If X has changed, we also update the scheduled send time t_now,
 * the inter-packet interval t_ipi, and the delta value.
133
 */ 
134 135
static void ccid3_hc_tx_update_x(struct sock *sk, struct timeval *now)

136
{
137
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
138
	const __u32 old_x = hctx->ccid3hctx_x;
139

140
	if (hctx->ccid3hctx_p > 0) {
141 142 143
		hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
						     hctx->ccid3hctx_rtt,
						     hctx->ccid3hctx_p);
144 145 146 147 148 149 150 151 152 153 154 155 156
		hctx->ccid3hctx_x = max_t(u32, min(hctx->ccid3hctx_x_calc,
						   hctx->ccid3hctx_x_recv * 2),
					       hctx->ccid3hctx_s / TFRC_T_MBI);

	} else if (timeval_delta(now, &hctx->ccid3hctx_t_ld) >=
							  hctx->ccid3hctx_rtt) {
		hctx->ccid3hctx_x = max(min(hctx->ccid3hctx_x_recv,
					    hctx->ccid3hctx_x      ) * 2,
					usecs_div(hctx->ccid3hctx_s,
					       	  hctx->ccid3hctx_rtt)   );
		hctx->ccid3hctx_t_ld = *now;
	} else
		ccid3_pr_debug("Not changing X\n");
157

158 159
	if (hctx->ccid3hctx_x != old_x)
		ccid3_update_send_time(hctx);
160 161
}

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/*
 * 	Track the mean packet size `s' (cf. RFC 4342, 5.3 and  RFC 3448, 4.1)
 * 	@len: DCCP packet payload size in bytes
 */
static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
{
	if (unlikely(len == 0))
		ccid3_pr_debug("Packet payload length is 0 - not updating\n");
	else
		hctx->ccid3hctx_s = hctx->ccid3hctx_s == 0 ? len :
				    (9 * hctx->ccid3hctx_s + len) / 10;
	/*
	 * Note: We could do a potential optimisation here - when `s' changes,
	 *	 recalculate sending rate and consequently t_ipi, t_delta, and
	 *	 t_now. This is however non-standard, and the benefits are not
	 *	 clear, so it is currently left out.
	 */
}

181 182 183
static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
	struct sock *sk = (struct sock *)data;
184
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
185
	unsigned long t_nfb = USEC_PER_SEC / 5;
186 187 188 189 190

	bh_lock_sock(sk);
	if (sock_owned_by_user(sk)) {
		/* Try again later. */
		/* XXX: set some sensible MIB */
191
		goto restart_timer;
192 193 194 195 196 197 198
	}

	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:
199 200 201
		/* RFC 3448, 4.4: Halve send rate directly */
		hctx->ccid3hctx_x = min_t(u32, hctx->ccid3hctx_x / 2,
					       hctx->ccid3hctx_s / TFRC_T_MBI);
202

203 204 205 206
		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),
207
			       hctx->ccid3hctx_x);
208 209
		/* The value of R is still undefined and so we can not recompute
		 * the timout value. Keep initial value as per [RFC 4342, 5]. */
210
		t_nfb = TFRC_INITIAL_TIMEOUT;
211
		ccid3_update_send_time(hctx);
212 213
		break;
	case TFRC_SSTATE_FBACK:
214 215 216 217 218
		/*
		 * Check if IDLE since last timeout and recv rate is less than
		 * 4 packets per RTT
		 */
		if (!hctx->ccid3hctx_idle ||
219 220
		    (hctx->ccid3hctx_x_recv >=
		     4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
221 222
			struct timeval now;

223 224
			ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
				       dccp_role(sk), sk,
225 226 227
				       ccid3_tx_state_name(hctx->ccid3hctx_state));
			/* Halve sending rate */

228
			/*  If (p == 0 || X_calc > 2 * X_recv)
229 230 231 232
			 *    X_recv = max(X_recv / 2, s / (2 * t_mbi));
			 *  Else
			 *    X_recv = X_calc / 4;
			 */
233
			BUG_ON(hctx->ccid3hctx_p && !hctx->ccid3hctx_x_calc);
234

235
			if (hctx->ccid3hctx_p  == 0 ||
236 237
			    hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
				hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
238
								    hctx->ccid3hctx_s / (2 * TFRC_T_MBI));
239 240 241 242
			else
				hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;

			/* Update sending rate */
243 244
			dccp_timestamp(sk, &now);
			ccid3_hc_tx_update_x(sk, &now);
245
		}
246 247
		/*
		 * Schedule no feedback timer to expire in
248 249
		 * max(t_RTO, 2 * s/X)  =  max(t_RTO, 2 * t_ipi)
		 * See comments in packet_recv() regarding the value of t_RTO.
250
		 */
251
		t_nfb = max(hctx->ccid3hctx_t_rto, 2 * hctx->ccid3hctx_t_ipi);
252
		break;
253 254 255 256
	case TFRC_SSTATE_NO_SENT:
		DCCP_BUG("Illegal %s state NO_SENT, sk=%p", dccp_role(sk), sk);
		/* fall through */
	case TFRC_SSTATE_TERM:
257 258 259 260
		goto out;
	}

	hctx->ccid3hctx_idle = 1;
261 262 263

restart_timer:
	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
264
		           jiffies + usecs_to_jiffies(t_nfb));
265 266 267 268 269
out:
	bh_unlock_sock(sk);
	sock_put(sk);
}

270 271 272 273 274 275
/*
 * returns
 *   > 0: delay (in msecs) that should pass before actually sending
 *   = 0: can send immediately
 *   < 0: error condition; do not send packet
 */
276
static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
277 278
{
	struct dccp_sock *dp = dccp_sk(sk);
279
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
280
	struct dccp_tx_hist_entry *new_packet;
281
	struct timeval now;
282
	long delay;
283

284
	BUG_ON(hctx == NULL);
285

286
	/*
287 288 289
	 * 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.
290
	 */
291
	if (unlikely(skb->len == 0))
292
		return -EBADMSG;
293 294

	/* See if last packet allocated was not sent */
295 296
	new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
	if (new_packet == NULL || new_packet->dccphtx_sent) {
297
		new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
298
						    GFP_ATOMIC);
299

300
		if (unlikely(new_packet == NULL)) {
301 302
			DCCP_WARN("%s, sk=%p, not enough mem to add to history,"
				  "send refused\n", dccp_role(sk), sk);
303
			return -ENOBUFS;
304 305
		}

306
		dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
307 308
	}

309
	dccp_timestamp(sk, &now);
310 311 312

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
313 314
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
			       jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
315 316 317 318
		hctx->ccid3hctx_last_win_count	 = 0;
		hctx->ccid3hctx_t_last_win_count = now;
		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);

319
		/* Set initial sending rate to 1 packet per second */
320
		ccid3_hc_tx_update_s(hctx, skb->len);
321 322
		hctx->ccid3hctx_x     = hctx->ccid3hctx_s;

323 324 325 326 327 328
		/* 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 */
329 330 331 332
		hctx->ccid3hctx_t_nom = now;
		break;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
333 334 335 336 337 338 339 340 341
		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.
		 */
342
		if (delay - (long)hctx->ccid3hctx_delta >= 0)
343
			return delay / 1000L;
344
		break;
345 346
	case TFRC_SSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
347
		return -EINVAL;
348 349
	}

350 351 352 353 354 355 356
	/* 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;
357 358
}

359
static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
360
{
361 362
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
363
	struct timeval now;
364 365
	unsigned long quarter_rtt;
	struct dccp_tx_hist_entry *packet;
366

367
	BUG_ON(hctx == NULL);
368

369
	dccp_timestamp(sk, &now);
370

371
	ccid3_hc_tx_update_s(hctx, len);
372

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
	packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
	if (unlikely(packet == NULL)) {
		DCCP_WARN("packet doesn't exist in history!\n");
		return;
	}
	if (unlikely(packet->dccphtx_sent)) {
		DCCP_WARN("no unsent packet in history!\n");
		return;
	}
	packet->dccphtx_tstamp = now;
	packet->dccphtx_seqno  = dp->dccps_gss;
	/*
	 * Check if win_count have changed
	 * Algorithm in "8.1. Window Counter Value" in RFC 4342.
	 */
	quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
	if (likely(hctx->ccid3hctx_rtt > 8))
		quarter_rtt /= hctx->ccid3hctx_rtt / 4;
391

392 393 394 395 396 397 398 399 400 401
	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;
		ccid3_pr_debug("%s, sk=%p, window changed from "
			       "%u to %u!\n",
			       dccp_role(sk), sk,
			       packet->dccphtx_ccval,
			       hctx->ccid3hctx_last_win_count);
	}
402

403 404 405
	hctx->ccid3hctx_idle = 0;
	packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
	packet->dccphtx_sent = 1;
406 407 408 409
}

static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
410 411
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
412
	struct ccid3_options_received *opt_recv;
413
	struct dccp_tx_hist_entry *packet;
414
	struct timeval now;
415
	unsigned long t_nfb;
416
	u32 pinv;
417
	long r_sample, t_elapsed;
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 433
		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
						 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 443 444 445 446 447 448
		/* Update receive rate */
		hctx->ccid3hctx_x_recv = opt_recv->ccid3or_receive_rate;

		/* Update loss event rate */
		pinv = opt_recv->ccid3or_loss_event_rate;
		if (pinv == ~0U || pinv == 0)
			hctx->ccid3hctx_p = 0;
449 450
		else
 			hctx->ccid3hctx_p = 1000000 / pinv;
451

452
		dccp_timestamp(sk, &now);
453 454 455 456 457 458 459 460 461 462 463 464 465

		/*
		 * Calculate new round trip sample as per [RFC 3448, 4.3] by
		 * 	R_sample  =  (now - t_recvdata) - t_elapsed
		 */
		r_sample  = timeval_delta(&now, &packet->dccphtx_tstamp);
		t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;

		if (unlikely(r_sample <= 0)) {
			DCCP_WARN("WARNING: R_sample (%ld) <= 0!\n", r_sample);
			r_sample = 0;
		} else if (unlikely(r_sample <= t_elapsed))
			DCCP_WARN("WARNING: r_sample=%ldus <= t_elapsed=%ldus\n",
466
				  r_sample, t_elapsed);
467 468
		else
			r_sample -= t_elapsed;
469 470 471 472 473 474 475 476 477 478

		/* 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) {
479 480 481 482 483 484 485 486 487
			/* Use Larger Initial Windows [RFC 4342, sec. 5]
			 * We deviate in that we use `s' instead of `MSS'. */
			u16 w_init = max(    4 * hctx->ccid3hctx_s,
					 max(2 * hctx->ccid3hctx_s, 4380));
			hctx->ccid3hctx_rtt  = r_sample;
			hctx->ccid3hctx_x    = usecs_div(w_init, r_sample);
			hctx->ccid3hctx_t_ld = now;

			ccid3_update_send_time(hctx);
488

489 490 491 492
			ccid3_pr_debug("%s(%p), s=%u, w_init=%u, "
				       "R_sample=%ldus, X=%u\n", dccp_role(sk),
				       sk, hctx->ccid3hctx_s, w_init, r_sample,
				       hctx->ccid3hctx_x);
493

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

499
			ccid3_hc_tx_update_x(sk, &now);
500

501 502 503 504 505 506
			ccid3_pr_debug("%s(%p), RTT=%uus (sample=%ldus), s=%u, "
				       "p=%u, X_calc=%u, X=%u\n", dccp_role(sk),
				       sk, hctx->ccid3hctx_rtt, r_sample,
				       hctx->ccid3hctx_s, hctx->ccid3hctx_p,
				       hctx->ccid3hctx_x_calc,
				       hctx->ccid3hctx_x);
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
		/*
		 * As we have calculated new ipi, delta, t_nom it is possible that
517
		 * we now can send a packet, so wake up dccp_wait_for_ccid
518 519
		 */
		sk->sk_write_space(sk);
520

521 522 523 524 525 526
		/*
		 * Update timeout interval for the nofeedback timer.
		 * We use a configuration option to increase the lower bound.
		 * This can help avoid triggering the nofeedback timer too often
		 * ('spinning') on LANs with small RTTs.
		 */
527
		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
528 529
						   CONFIG_IP_DCCP_CCID3_RTO *
						   (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 537 538
		ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
			       "expire in %lu jiffies (%luus)\n",
			       dccp_role(sk), sk,
539
			       usecs_to_jiffies(t_nfb), t_nfb);
540 541

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

		/* set idle flag */
		hctx->ccid3hctx_idle = 1;   
		break;
G
Gerrit Renker 已提交
547
	case TFRC_SSTATE_NO_SENT:
548 549
		if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT)
			DCCP_WARN("Illegal ACK received - no packet sent\n");
G
Gerrit Renker 已提交
550 551
		/* fall through */
	case TFRC_SSTATE_TERM:		/* ignore feedback when closing */
552 553 554 555
		break;
	}
}

556
static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
557
{
558
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
559

560 561
	BUG_ON(hctx == NULL);

562 563 564
	if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
		DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
	return 0;
565 566 567
}

static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
568 569
				     unsigned char len, u16 idx,
				     unsigned char *value)
570 571
{
	int rc = 0;
572 573
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
574 575
	struct ccid3_options_received *opt_recv;

576
	BUG_ON(hctx == NULL);
577 578 579 580 581 582 583 584 585 586 587 588 589

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

	return rc;
}

628
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
629
{
630
	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
631

632
	hctx->ccid3hctx_s     = 0;
633 634
	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
635 636 637

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

	return 0;
}

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

	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 */
653
	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
654 655 656 657 658 659
}

/*
 * RX Half Connection methods
 */

660
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
661 662 663 664 665 666 667 668 669 670 671 672
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

673 674
static void ccid3_hc_rx_set_state(struct sock *sk,
				  enum ccid3_hc_rx_states state)
675
{
676
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
677 678 679
	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
680 681
		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
		       ccid3_rx_state_name(state));
682 683 684 685
	WARN_ON(state == oldstate);
	hcrx->ccid3hcrx_state = state;
}

686 687 688 689 690 691 692 693 694
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;
}

695 696
static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
697
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
698
	struct dccp_sock *dp = dccp_sk(sk);
699
	struct dccp_rx_hist_entry *packet;
700
	struct timeval now;
701 702 703

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

704
	dccp_timestamp(sk, &now);
705

706 707 708 709 710
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
		hcrx->ccid3hcrx_x_recv = 0;
		break;
	case TFRC_RSTATE_DATA: {
711 712
		const u32 delta = timeval_delta(&now,
					&hcrx->ccid3hcrx_tstamp_last_feedback);
713 714
		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
						   delta);
715 716
	}
		break;
717 718
	case TFRC_RSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
719 720 721
		return;
	}

722
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
723
	if (unlikely(packet == NULL)) {
724 725
		DCCP_WARN("%s, sk=%p, no data packet in history!\n",
			  dccp_role(sk), sk);
726 727 728
		return;
	}

729
	hcrx->ccid3hcrx_tstamp_last_feedback = now;
I
Ian McDonald 已提交
730
	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
731 732 733
	hcrx->ccid3hcrx_bytes_recv	     = 0;

	/* Convert to multiples of 10us */
734 735
	hcrx->ccid3hcrx_elapsed_time =
			timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
736 737 738 739
	if (hcrx->ccid3hcrx_p == 0)
		hcrx->ccid3hcrx_pinv = ~0;
	else
		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
740
	dp->dccps_hc_rx_insert_options = 1;
741 742 743
	dccp_send_ack(sk);
}

744
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
745
{
746
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
747
	__be32 x_recv, pinv;
748

749 750 751
	BUG_ON(hcrx == NULL);

	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
752
		return 0;
753

I
Ian McDonald 已提交
754
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
755 756

	if (dccp_packet_without_ack(skb))
757 758
		return 0;

759 760
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
761 762 763 764 765 766 767 768 769 770 771 772

	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;
773 774 775 776 777 778 779 780
}

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

static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
{
781
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
782
	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
783
	u32 rtt, delta, x_recv, fval, p, tmp2;
784
	struct timeval tstamp = { 0, };
785 786 787 788 789
	int interval = 0;
	int win_count = 0;
	int step = 0;
	u64 tmp1;

790 791 792
	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
				 dccphrx_node) {
		if (dccp_rx_hist_entry_data_packet(entry)) {
793 794 795 796
			tail = entry;

			switch (step) {
			case 0:
797
				tstamp	  = entry->dccphrx_tstamp;
798
				win_count = entry->dccphrx_ccval;
799 800 801
				step = 1;
				break;
			case 1:
802
				interval = win_count - entry->dccphrx_ccval;
803 804 805 806 807 808 809 810 811
				if (interval < 0)
					interval += TFRC_WIN_COUNT_LIMIT;
				if (interval > 4)
					goto found;
				break;
			}
		}
	}

812
	if (unlikely(step == 0)) {
813 814
		DCCP_WARN("%s, sk=%p, packet history has no data packets!\n",
			  dccp_role(sk), sk);
815 816 817
		return ~0;
	}

818
	if (unlikely(interval == 0)) {
819 820
		DCCP_WARN("%s, sk=%p, Could not find a win_count interval > 0."
			  "Defaulting to 1\n", dccp_role(sk), sk);
821 822 823
		interval = 1;
	}
found:
I
Ian McDonald 已提交
824
	if (!tail) {
825
		DCCP_CRIT("tail is null\n");
I
Ian McDonald 已提交
826 827
		return ~0;
	}
828
	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
829 830
	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
		       dccp_role(sk), sk, rtt);
831 832 833 834 835

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

837 838 839
	dccp_timestamp(sk, &tstamp);
	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
840

I
Ian McDonald 已提交
841 842 843
	if (x_recv == 0)
		x_recv = hcrx->ccid3hcrx_x_recv;

844 845 846
	tmp1 = (u64)x_recv * (u64)rtt;
	do_div(tmp1,10000000);
	tmp2 = (u32)tmp1;
I
Ian McDonald 已提交
847 848

	if (!tmp2) {
849
		DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt);
I
Ian McDonald 已提交
850 851 852
		return ~0;
	}

853 854
	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
	/* do not alter order above or you will get overflow on 32 bit */
855
	p = tfrc_calc_x_reverse_lookup(fval);
856 857
	ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
858 859 860 861 862 863 864 865 866

	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)
{
867
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
868
	struct dccp_li_hist_entry *head;
I
Ian McDonald 已提交
869
	u64 seq_temp;
870

I
Ian McDonald 已提交
871 872 873 874
	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;
875

876 877 878
		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 已提交
879 880 881 882
	} else {
		struct dccp_li_hist_entry *entry;
		struct list_head *tail;

883 884
		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
		   struct dccp_li_hist_entry, dccplih_node);
I
Ian McDonald 已提交
885 886 887 888 889 890 891
		/* 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);
892
		entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
I
Ian McDonald 已提交
893 894

		if (entry == NULL) {
895
			DCCP_BUG("out of memory - can not allocate entry");
896
			return;
I
Ian McDonald 已提交
897 898 899 900 901 902 903 904 905 906 907 908 909
		}

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

I
Ian McDonald 已提交
912 913
static int ccid3_hc_rx_detect_loss(struct sock *sk,
                                    struct dccp_rx_hist_entry *packet)
914
{
915
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
I
Ian McDonald 已提交
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
	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;
	}

932

I
Ian McDonald 已提交
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
	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;
962 963 964 965
}

static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
966
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
967
	const struct dccp_options_received *opt_recv;
968
	struct dccp_rx_hist_entry *packet;
969
	struct timeval now;
I
Ian McDonald 已提交
970
	u32 p_prev, rtt_prev, r_sample, t_elapsed;
971
	int loss, payload_size;
972

973
	BUG_ON(hcrx == NULL);
974

975
	opt_recv = &dccp_sk(sk)->dccps_options_received;
976

977 978 979 980 981
	switch (DCCP_SKB_CB(skb)->dccpd_type) {
	case DCCP_PKT_ACK:
		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			return;
	case DCCP_PKT_DATAACK:
982
		if (opt_recv->dccpor_timestamp_echo == 0)
983
			break;
I
Ian McDonald 已提交
984
		rtt_prev = hcrx->ccid3hcrx_rtt;
985
		dccp_timestamp(sk, &now);
986 987 988 989 990
		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))
991 992
			DCCP_WARN("r_sample=%uus, t_elapsed=%uus\n",
				  r_sample, t_elapsed);
993 994 995 996 997 998 999 1000 1001
		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 已提交
1002 1003
		if (rtt_prev != hcrx->ccid3hcrx_rtt)
			ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
1004 1005
				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
				       opt_recv->dccpor_elapsed_time);
1006 1007 1008
		break;
	case DCCP_PKT_DATA:
		break;
1009
	default: /* We're not interested in other packet types, move along */
1010 1011 1012
		return;
	}

1013
	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
1014
					skb, GFP_ATOMIC);
1015
	if (unlikely(packet == NULL)) {
1016 1017
		DCCP_WARN("%s, sk=%p, Not enough mem to add rx packet "
			  "to history, consider it lost!\n", dccp_role(sk), sk);
1018 1019 1020
		return;
	}

I
Ian McDonald 已提交
1021
	loss = ccid3_hc_rx_detect_loss(sk, packet);
1022 1023 1024 1025

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

1026 1027 1028
	payload_size = skb->len - dccp_hdr(skb)->dccph_doff * 4;
	ccid3_hc_rx_update_s(hcrx, payload_size);

1029 1030
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
1031 1032 1033 1034
		ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
			       "feedback\n",
			       dccp_role(sk), sk,
			       dccp_state_name(sk->sk_state), skb);
1035 1036 1037 1038
		ccid3_hc_rx_send_feedback(sk);
		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
		return;
	case TFRC_RSTATE_DATA:
1039
		hcrx->ccid3hcrx_bytes_recv += payload_size;
I
Ian McDonald 已提交
1040
		if (loss)
1041 1042
			break;

1043
		dccp_timestamp(sk, &now);
1044 1045 1046 1047
		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
		    hcrx->ccid3hcrx_rtt) {
			hcrx->ccid3hcrx_tstamp_last_ack = now;
			ccid3_hc_rx_send_feedback(sk);
1048
		}
1049
		return;
1050 1051
	case TFRC_RSTATE_TERM:
		DCCP_BUG("Illegal %s state TERM, sk=%p", dccp_role(sk), sk);
1052 1053 1054 1055
		return;
	}

	/* Dealing with packet loss */
1056 1057
	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
1058 1059 1060 1061

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

1065
		/* Scaling up by 1000000 as fixed decimal */
I
Ian McDonald 已提交
1066 1067
		if (i_mean != 0)
			hcrx->ccid3hcrx_p = 1000000 / i_mean;
1068 1069
	} else
		DCCP_BUG("empty loss history");
1070 1071 1072 1073 1074 1075 1076

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

1077
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
1078
{
1079
	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
1080 1081 1082 1083 1084

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

	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
1085
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
1086
	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
1087
	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
1088
	hcrx->ccid3hcrx_s   = 0;
1089
	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
1090 1091 1092 1093 1094
	return 0;
}

static void ccid3_hc_rx_exit(struct sock *sk)
{
1095
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1096

1097
	BUG_ON(hcrx == NULL);
1098 1099 1100 1101

	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);

	/* Empty packet history */
1102
	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
1103 1104

	/* Empty loss interval history */
1105
	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
1106 1107
}

1108 1109
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
{
1110
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1111

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

1116
	BUG_ON(hcrx == NULL);
1117 1118 1119 1120 1121 1122 1123 1124

	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)
{
1125
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
1126

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

1131
	BUG_ON(hctx == NULL);
1132 1133 1134 1135 1136

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

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 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
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;
}

1191
static struct ccid_operations ccid3 = {
I
Ian McDonald 已提交
1192
	.ccid_id		   = DCCPC_CCID3,
1193 1194
	.ccid_name		   = "ccid3",
	.ccid_owner		   = THIS_MODULE,
1195
	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),
1196 1197 1198 1199 1200 1201 1202
	.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,
1203
	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
1204 1205 1206 1207
	.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,
1208 1209
	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
1210 1211
	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
1212 1213
};
 
1214
#ifdef CONFIG_IP_DCCP_CCID3_DEBUG
1215 1216
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
1217
#endif
1218 1219 1220

static __init int ccid3_module_init(void)
{
1221
	int rc = -ENOBUFS;
1222

1223 1224
	ccid3_rx_hist = dccp_rx_hist_new("ccid3");
	if (ccid3_rx_hist == NULL)
1225 1226
		goto out;

1227 1228 1229
	ccid3_tx_hist = dccp_tx_hist_new("ccid3");
	if (ccid3_tx_hist == NULL)
		goto out_free_rx;
1230

1231 1232
	ccid3_li_hist = dccp_li_hist_new("ccid3");
	if (ccid3_li_hist == NULL)
1233
		goto out_free_tx;
1234 1235 1236 1237 1238 1239

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

1241
out_free_loss_interval_history:
1242 1243
	dccp_li_hist_delete(ccid3_li_hist);
	ccid3_li_hist = NULL;
1244 1245 1246 1247 1248 1249
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;
1250 1251 1252 1253 1254 1255 1256 1257
	goto out;
}
module_init(ccid3_module_init);

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

1258 1259 1260
	if (ccid3_tx_hist != NULL) {
		dccp_tx_hist_delete(ccid3_tx_hist);
		ccid3_tx_hist = NULL;
1261
	}
1262 1263 1264
	if (ccid3_rx_hist != NULL) {
		dccp_rx_hist_delete(ccid3_rx_hist);
		ccid3_rx_hist = NULL;
1265
	}
1266 1267 1268
	if (ccid3_li_hist != NULL) {
		dccp_li_hist_delete(ccid3_li_hist);
		ccid3_li_hist = NULL;
1269 1270 1271 1272
	}
}
module_exit(ccid3_module_exit);

1273
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1274
	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1275 1276 1277
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
MODULE_ALIAS("net-dccp-ccid-3");