ccid3.c 36.9 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
static int ccid3_debug;
64

65
#ifdef CCID3_DEBUG
66 67 68 69 70 71 72 73
#define ccid3_pr_debug(format, a...) \
	do { if (ccid3_debug) \
		printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
	} while (0)
#else
#define ccid3_pr_debug(format, a...)
#endif

74 75
static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
76
static struct dccp_li_hist *ccid3_li_hist;
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91

#ifdef CCID3_DEBUG
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

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

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
99 100
		       dccp_role(sk), sk, ccid3_tx_state_name(oldstate),
		       ccid3_tx_state_name(state));
101 102 103 104 105 106 107
	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)
{
108 109 110 111 112 113 114
	/*
	 * If no feedback spec says t_ipi is 1 second (set elsewhere and then
	 * doubles after every no feedback timer (separate function)
	 */
	if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
		hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
						  hctx->ccid3hctx_x);
115 116 117 118 119
}

/* 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)
{
120 121
	hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
					   TFRC_OPSYS_HALF_TIME_GRAN);
122 123 124 125 126 127 128 129 130 131 132 133 134 135
}

/*
 * 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)
{
136
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
137

138 139
	/* To avoid large error in calcX */
	if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
140 141 142
		hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s,
						     hctx->ccid3hctx_rtt,
						     hctx->ccid3hctx_p);
143 144 145 146
		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));
147 148 149
	} else {
		struct timeval now;

150
		dccp_timestamp(sk, &now);
151 152
	       	if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
		    hctx->ccid3hctx_rtt) {
153 154 155 156
			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));
157 158
			hctx->ccid3hctx_t_ld = now;
		}
159 160 161 162 163 164 165
	}
}

static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
{
	struct sock *sk = (struct sock *)data;
	unsigned long next_tmout = 0;
166
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
167 168 169 170 171

	bh_lock_sock(sk);
	if (sock_owned_by_user(sk)) {
		/* Try again later. */
		/* XXX: set some sensible MIB */
172 173
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
			       jiffies + HZ / 5);
174 175 176 177 178 179 180 181 182 183 184 185
		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_TERM:
		goto out;
	case TFRC_SSTATE_NO_FBACK:
		/* Halve send rate */
		hctx->ccid3hctx_x /= 2;
186 187
		if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
					 TFRC_MAX_BACK_OFF_TIME))
188 189
			hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
					     TFRC_MAX_BACK_OFF_TIME);
190

191 192 193 194
		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),
195
			       hctx->ccid3hctx_x);
196 197
		next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
						      hctx->ccid3hctx_x),
198 199 200 201 202 203
					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
		 */
204 205
		break;
	case TFRC_SSTATE_FBACK:
206 207 208 209 210
		/*
		 * Check if IDLE since last timeout and recv rate is less than
		 * 4 packets per RTT
		 */
		if (!hctx->ccid3hctx_idle ||
211 212
		    (hctx->ccid3hctx_x_recv >=
		     4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
213 214
			ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
				       dccp_role(sk), sk,
215 216 217 218 219 220 221 222
				       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;
			 */
223 224
			BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P &&
			       hctx->ccid3hctx_x_calc == 0);
225 226 227 228 229 230 231 232 233 234 235 236

			/* 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);
		}
237 238 239 240
		/*
		 * Schedule no feedback timer to expire in
		 * max(4 * R, 2 * s / X)
		 */
241
		next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, 
242 243
					2 * usecs_div(hctx->ccid3hctx_s,
						      hctx->ccid3hctx_x));
244 245
		break;
	default:
246 247
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk,
			 hctx->ccid3hctx_state);
248 249 250 251
		goto out;
	}

	sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
252
		      jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
253 254 255 256 257 258
	hctx->ccid3hctx_idle = 1;
out:
	bh_unlock_sock(sk);
	sock_put(sk);
}

259 260
static int ccid3_hc_tx_send_packet(struct sock *sk,
				   struct sk_buff *skb, int len)
261 262
{
	struct dccp_sock *dp = dccp_sk(sk);
263
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
264
	struct dccp_tx_hist_entry *new_packet;
265
	struct timeval now;
266
	long delay;
267 268
	int rc = -ENOTCONN;

269
	BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
270

271
	/* Check if pure ACK or Terminating*/
272
	/*
273 274
	 * XXX: We only call this function for DATA and DATAACK, on, these
	 * packets can have zero length, but why the comment about "pure ACK"?
275
	 */
276
	if (unlikely(len == 0))
277 278 279
		goto out;

	/* See if last packet allocated was not sent */
280 281
	new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
	if (new_packet == NULL || new_packet->dccphtx_sent) {
282 283
		new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
						    SLAB_ATOMIC);
284 285

		rc = -ENOBUFS;
286 287 288 289
		if (unlikely(new_packet == NULL)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough "
				       "mem to add to history, send refused\n",
				       __FUNCTION__, dccp_role(sk), sk);
290 291 292
			goto out;
		}

293
		dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
294 295
	}

296
	dccp_timestamp(sk, &now);
297 298 299

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
300 301
		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
			       jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
302 303 304
		hctx->ccid3hctx_last_win_count	 = 0;
		hctx->ccid3hctx_t_last_win_count = now;
		ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
305
		hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI;
306 307 308

		/* Set nominal send time for initial packet */
		hctx->ccid3hctx_t_nom = now;
309 310
		timeval_add_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
311 312 313 314 315
		ccid3_calc_new_delta(hctx);
		rc = 0;
		break;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
316 317
		delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
		         hctx->ccid3hctx_delta);
318
		delay /= -1000;
319
		/* divide by -1000 is to convert to ms and get sign right */
320
		rc = delay > 0 ? delay : 0;
321 322
		break;
	default:
323 324
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk,
			 hctx->ccid3hctx_state);
325 326 327 328 329
		rc = -EINVAL;
		break;
	}

	/* Can we send? if so add options and add to packet history */
330 331
	if (rc == 0) {
		dp->dccps_hc_tx_insert_options = 1;
332
		new_packet->dccphtx_ccval =
333 334
			DCCP_SKB_CB(skb)->dccpd_ccval =
				hctx->ccid3hctx_last_win_count;
I
Ian McDonald 已提交
335 336
		timeval_add_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
337
	}
338 339 340 341 342 343
out:
	return rc;
}

static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
{
344 345
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
346 347
	struct timeval now;

348
	BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
349

350
	dccp_timestamp(sk, &now);
351 352 353 354

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

357
		packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
358 359 360
		if (unlikely(packet == NULL)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't "
				       "exists in history!\n", __FUNCTION__);
361 362
			return;
		}
363 364 365
		if (unlikely(packet->dccphtx_sent)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in "
				       "history!\n", __FUNCTION__);
366 367
			return;
		}
368 369
		packet->dccphtx_tstamp = now;
		packet->dccphtx_seqno  = dp->dccps_gss;
370
		/*
371
		 * Check if win_count have changed
372
		 * Algorithm in "8.1. Window Counter Value" in RFC 4342.
373
		 */
374 375 376 377
		quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
		if (likely(hctx->ccid3hctx_rtt > 8))
			quarter_rtt /= hctx->ccid3hctx_rtt / 4;

378 379 380 381
		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;
382 383
			ccid3_pr_debug("%s, sk=%p, window changed from "
				       "%u to %u!\n",
384
				       dccp_role(sk), sk,
385
				       packet->dccphtx_ccval,
386 387
				       hctx->ccid3hctx_last_win_count);
		}
388

389
		hctx->ccid3hctx_idle = 0;
390
		packet->dccphtx_rtt  = hctx->ccid3hctx_rtt;
391
		packet->dccphtx_sent = 1;
392 393 394 395 396 397 398 399
	} else
		ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
			       dccp_role(sk), sk, dp->dccps_gss);

	switch (hctx->ccid3hctx_state) {
	case TFRC_SSTATE_NO_SENT:
		/* if first wasn't pure ack */
		if (len != 0)
400 401
			printk(KERN_CRIT "%s: %s, First packet sent is noted "
					 "as a data packet\n",
402 403 404 405 406
			       __FUNCTION__, dccp_role(sk));
		return;
	case TFRC_SSTATE_NO_FBACK:
	case TFRC_SSTATE_FBACK:
		if (len > 0) {
I
Ian McDonald 已提交
407 408
			timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
409 410
			ccid3_calc_new_t_ipi(hctx);
			ccid3_calc_new_delta(hctx);
411 412
			timeval_add_usecs(&hctx->ccid3hctx_t_nom,
					  hctx->ccid3hctx_t_ipi);
413 414 415
		}
		break;
	default:
416 417
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk,
			 hctx->ccid3hctx_state);
418 419 420 421 422 423
		break;
	}
}

static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
424 425
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
426
	struct ccid3_options_received *opt_recv;
427
	struct dccp_tx_hist_entry *packet;
428
	struct timeval now;
429
	unsigned long next_tmout; 
I
Ian McDonald 已提交
430
	u32 t_elapsed;
431 432 433
	u32 pinv;
	u32 x_recv;
	u32 r_sample;
434

435
	BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM);
436 437 438 439 440 441 442 443

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

444
	t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10;
445 446 447 448 449 450 451 452 453 454 455 456
	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 */
457 458
		packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
						 DCCP_SKB_CB(skb)->dccpd_ack_seq);
459 460 461 462 463 464
		if (unlikely(packet == NULL)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno "
				       "%llu(%s) does't exist in history!\n",
				       __FUNCTION__, dccp_role(sk), sk,
			    (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,
				dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
465 466 467 468
			return;
		}

		/* Update RTT */
469 470
		dccp_timestamp(sk, &now);
		r_sample = timeval_delta(&now, &packet->dccphtx_tstamp);
471
		if (unlikely(r_sample <= t_elapsed))
472 473
			LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
				       "t_elapsed=%uus\n",
474 475 476
				       __FUNCTION__, r_sample, t_elapsed);
		else
			r_sample -= t_elapsed;
477 478 479 480 481 482 483 484 485 486 487 488 489

		/* 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
490 491
			hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
					      r_sample / 10;
492

493 494 495
		ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
			       "r_sample=%us\n", dccp_role(sk), sk,
			       hctx->ccid3hctx_rtt, r_sample);
496 497

		/* Update timeout interval */
498 499
		hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
					      USEC_PER_SEC);
500 501

		/* Update receive rate */
502
		hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */
503 504 505 506 507 508 509 510 511

		/* 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;
512 513
				ccid3_pr_debug("%s, sk=%p, Smallest p used!\n",
					       dccp_role(sk), sk);
514 515 516 517 518 519 520 521 522 523
			}
		}

		/* 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 */
524 525
		timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
526
		ccid3_calc_new_t_ipi(hctx);
527 528
		timeval_add_usecs(&hctx->ccid3hctx_t_nom,
				  hctx->ccid3hctx_t_ipi);
529 530 531
		ccid3_calc_new_delta(hctx);

		/* remove all packets older than the one acked from history */
532 533
		dccp_tx_hist_purge_older(ccid3_tx_hist,
					 &hctx->ccid3hctx_hist, packet);
534 535 536 537 538
		/*
		 * 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);
539

540 541 542 543
		/*
		 * Schedule no feedback timer to expire in
		 * max(4 * R, 2 * s / X)
		 */
544
		next_tmout = max(hctx->ccid3hctx_t_rto,
545 546 547
				 2 * usecs_div(hctx->ccid3hctx_s,
					       hctx->ccid3hctx_x));
			
548 549 550 551
		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); 
552 553

		sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 
554
			       jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
555 556 557 558 559

		/* set idle flag */
		hctx->ccid3hctx_idle = 1;   
		break;
	default:
560 561
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk,
			 hctx->ccid3hctx_state);
562 563 564 565
		break;
	}
}

566
static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
567
{
568
	const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
569

570 571
	BUG_ON(hctx == NULL);

572 573 574
	if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)
		DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
	return 0;
575 576 577
}

static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
578 579
				     unsigned char len, u16 idx,
				     unsigned char *value)
580 581
{
	int rc = 0;
582 583
	const struct dccp_sock *dp = dccp_sk(sk);
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
584 585
	struct ccid3_options_received *opt_recv;

586
	BUG_ON(hctx == NULL);
587 588 589 590 591 592 593 594 595 596 597 598 599

	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:
600 601 602 603
		if (unlikely(len != 4)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
				       "len for TFRC_OPT_LOSS_EVENT_RATE\n",
				       __FUNCTION__, dccp_role(sk), sk);
604 605
			rc = -EINVAL;
		} else {
606
			opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value);
607 608 609 610 611 612 613 614 615 616 617 618 619 620
			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:
621 622 623 624
		if (unlikely(len != 4)) {
			LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid "
				       "len for TFRC_OPT_RECEIVE_RATE\n",
				       __FUNCTION__, dccp_role(sk), sk);
625 626
			rc = -EINVAL;
		} else {
627
			opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value);
628 629 630 631 632 633 634 635 636 637
			ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
				       dccp_role(sk), sk,
				       opt_recv->ccid3or_receive_rate);
		}
		break;
	}

	return rc;
}

638
static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk)
639 640
{
	struct dccp_sock *dp = dccp_sk(sk);
641
	struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid);
642

643 644 645
	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
		hctx->ccid3hctx_s = dp->dccps_packet_size;
646 647 648
	else
		hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;

649 650
	/* Set transmission rate to 1 packet per second */
	hctx->ccid3hctx_x     = hctx->ccid3hctx_s;
651
	hctx->ccid3hctx_t_rto = USEC_PER_SEC;
652 653
	hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
	INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
654 655 656

	hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
	hctx->ccid3hctx_no_feedback_timer.data     = (unsigned long)sk;
657 658 659 660 661 662 663
	init_timer(&hctx->ccid3hctx_no_feedback_timer);

	return 0;
}

static void ccid3_hc_tx_exit(struct sock *sk)
{
664
	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
665 666 667 668 669 670 671

	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 */
672
	dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
}

/*
 * RX Half Connection methods
 */

#ifdef CCID3_DEBUG
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

692 693
static void ccid3_hc_rx_set_state(struct sock *sk,
				  enum ccid3_hc_rx_states state)
694
{
695
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
696 697 698
	enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;

	ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
699 700
		       dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
		       ccid3_rx_state_name(state));
701 702 703 704 705 706
	WARN_ON(state == oldstate);
	hcrx->ccid3hcrx_state = state;
}

static void ccid3_hc_rx_send_feedback(struct sock *sk)
{
707
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
708
	struct dccp_sock *dp = dccp_sk(sk);
709
	struct dccp_rx_hist_entry *packet;
710
	struct timeval now;
711 712 713

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

714
	dccp_timestamp(sk, &now);
715

716 717 718 719 720
	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
		hcrx->ccid3hcrx_x_recv = 0;
		break;
	case TFRC_RSTATE_DATA: {
721 722
		const u32 delta = timeval_delta(&now,
					&hcrx->ccid3hcrx_tstamp_last_feedback);
723 724
		hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv,
						   delta);
725 726 727
	}
		break;
	default:
728 729
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!", dccp_role(sk), sk,
			 hcrx->ccid3hcrx_state);
730 731 732
		return;
	}

733
	packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
734 735 736 737
	if (unlikely(packet == NULL)) {
		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet "
			       "in history!\n",
			       __FUNCTION__, dccp_role(sk), sk);
738 739 740
		return;
	}

741
	hcrx->ccid3hcrx_tstamp_last_feedback = now;
I
Ian McDonald 已提交
742
	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
743 744 745
	hcrx->ccid3hcrx_bytes_recv	     = 0;

	/* Convert to multiples of 10us */
746 747
	hcrx->ccid3hcrx_elapsed_time =
			timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
748 749 750 751
	if (hcrx->ccid3hcrx_p == 0)
		hcrx->ccid3hcrx_pinv = ~0;
	else
		hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
752
	dp->dccps_hc_rx_insert_options = 1;
753 754 755
	dccp_send_ack(sk);
}

756
static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
757
{
758
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
759
	__be32 x_recv, pinv;
760

761 762 763
	BUG_ON(hcrx == NULL);

	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
764
		return 0;
765

I
Ian McDonald 已提交
766
	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
767 768

	if (dccp_packet_without_ack(skb))
769 770
		return 0;

771 772
	x_recv = htonl(hcrx->ccid3hcrx_x_recv);
	pinv   = htonl(hcrx->ccid3hcrx_pinv);
773 774 775 776 777 778 779 780 781 782 783 784

	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;
785 786 787 788 789 790 791 792
}

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

static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
{
793
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
794
	struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
795
	u32 rtt, delta, x_recv, fval, p, tmp2;
796
	struct timeval tstamp = { 0, };
797 798 799 800 801
	int interval = 0;
	int win_count = 0;
	int step = 0;
	u64 tmp1;

802 803 804
	list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
				 dccphrx_node) {
		if (dccp_rx_hist_entry_data_packet(entry)) {
805 806 807 808
			tail = entry;

			switch (step) {
			case 0:
809
				tstamp	  = entry->dccphrx_tstamp;
810
				win_count = entry->dccphrx_ccval;
811 812 813
				step = 1;
				break;
			case 1:
814
				interval = win_count - entry->dccphrx_ccval;
815 816 817 818 819 820 821 822 823
				if (interval < 0)
					interval += TFRC_WIN_COUNT_LIMIT;
				if (interval > 4)
					goto found;
				break;
			}
		}
	}

824 825 826 827
	if (unlikely(step == 0)) {
		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history "
			       "contains no data packets!\n",
			       __FUNCTION__, dccp_role(sk), sk);
828 829 830
		return ~0;
	}

831 832 833 834
	if (unlikely(interval == 0)) {
		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a "
			       "win_count interval > 0. Defaulting to 1\n",
			       __FUNCTION__, dccp_role(sk), sk);
835 836 837
		interval = 1;
	}
found:
I
Ian McDonald 已提交
838 839 840 841 842
	if (!tail) {
		LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n",
		   __FUNCTION__);
		return ~0;
	}
843
	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
844 845 846 847 848
	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
		       dccp_role(sk), sk, rtt);
	if (rtt == 0)
		rtt = 1;

849 850 851
	dccp_timestamp(sk, &tstamp);
	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
852

I
Ian McDonald 已提交
853 854 855
	if (x_recv == 0)
		x_recv = hcrx->ccid3hcrx_x_recv;

856 857 858
	tmp1 = (u64)x_recv * (u64)rtt;
	do_div(tmp1,10000000);
	tmp2 = (u32)tmp1;
I
Ian McDonald 已提交
859 860 861 862 863 864 865 866

	if (!tmp2) {
		LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 "
		   "%s: x_recv = %u, rtt =%u\n",
		   __FUNCTION__, x_recv, rtt);
		return ~0;
	}

867 868
	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
	/* do not alter order above or you will get overflow on 32 bit */
869
	p = tfrc_calc_x_reverse_lookup(fval);
870 871
	ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
		       "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
872 873 874 875 876 877 878 879 880

	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)
{
881
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
882
	struct dccp_li_hist_entry *head;
I
Ian McDonald 已提交
883
	u64 seq_temp;
884

I
Ian McDonald 已提交
885 886 887 888
	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;
889

890 891 892
		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 已提交
893 894 895 896
	} else {
		struct dccp_li_hist_entry *entry;
		struct list_head *tail;

897 898
		head = list_entry(hcrx->ccid3hcrx_li_hist.next,
		   struct dccp_li_hist_entry, dccplih_node);
I
Ian McDonald 已提交
899 900 901 902 903 904 905 906 907 908 909 910
		/* 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) {
			printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__);
			dump_stack();
911
			return;
I
Ian McDonald 已提交
912 913 914 915 916 917 918 919 920 921 922 923 924
		}

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

I
Ian McDonald 已提交
927 928
static int ccid3_hc_rx_detect_loss(struct sock *sk,
                                    struct dccp_rx_hist_entry *packet)
929
{
930
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
I
Ian McDonald 已提交
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
	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;
	}

947

I
Ian McDonald 已提交
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
	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;
977 978 979 980
}

static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
{
981
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
982
	const struct dccp_options_received *opt_recv;
983
	struct dccp_rx_hist_entry *packet;
984 985
	struct timeval now;
	u8 win_count;
I
Ian McDonald 已提交
986 987
	u32 p_prev, rtt_prev, r_sample, t_elapsed;
	int loss;
988

989 990
	BUG_ON(hcrx == NULL ||
	       !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
991 992
		 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));

993
	opt_recv = &dccp_sk(sk)->dccps_options_received;
994

995 996 997 998 999
	switch (DCCP_SKB_CB(skb)->dccpd_type) {
	case DCCP_PKT_ACK:
		if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
			return;
	case DCCP_PKT_DATAACK:
1000
		if (opt_recv->dccpor_timestamp_echo == 0)
1001
			break;
I
Ian McDonald 已提交
1002
		rtt_prev = hcrx->ccid3hcrx_rtt;
1003
		dccp_timestamp(sk, &now);
1004 1005 1006 1007 1008
		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))
1009 1010
			LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, "
				       "t_elapsed=%uus\n",
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
				       __FUNCTION__, r_sample, t_elapsed);
		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 已提交
1021 1022
		if (rtt_prev != hcrx->ccid3hcrx_rtt)
			ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
1023 1024
				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
				       opt_recv->dccpor_elapsed_time);
1025 1026 1027
		break;
	case DCCP_PKT_DATA:
		break;
1028
	default: /* We're not interested in other packet types, move along */
1029 1030 1031
		return;
	}

1032
	packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp,
1033
					skb, SLAB_ATOMIC);
1034 1035 1036 1037
	if (unlikely(packet == NULL)) {
		LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to "
				"add rx packet to history, consider it lost!\n",
			       __FUNCTION__, dccp_role(sk), sk);
1038 1039 1040
		return;
	}

1041
	win_count = packet->dccphrx_ccval;
1042

I
Ian McDonald 已提交
1043
	loss = ccid3_hc_rx_detect_loss(sk, packet);
1044 1045 1046 1047 1048 1049

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

	switch (hcrx->ccid3hcrx_state) {
	case TFRC_RSTATE_NO_DATA:
1050 1051 1052 1053
		ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
			       "feedback\n",
			       dccp_role(sk), sk,
			       dccp_state_name(sk->sk_state), skb);
1054 1055 1056 1057
		ccid3_hc_rx_send_feedback(sk);
		ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
		return;
	case TFRC_RSTATE_DATA:
1058 1059
		hcrx->ccid3hcrx_bytes_recv += skb->len -
					      dccp_hdr(skb)->dccph_doff * 4;
I
Ian McDonald 已提交
1060
		if (loss)
1061 1062
			break;

1063
		dccp_timestamp(sk, &now);
1064 1065 1066 1067
		if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
		    hcrx->ccid3hcrx_rtt) {
			hcrx->ccid3hcrx_tstamp_last_ack = now;
			ccid3_hc_rx_send_feedback(sk);
1068
		}
1069
		return;
1070
	default:
1071 1072
		DCCP_BUG("%s, sk=%p, Illegal state (%d)!",  dccp_role(sk), sk,
			 hcrx->ccid3hcrx_state);
1073 1074 1075 1076
		return;
	}

	/* Dealing with packet loss */
1077 1078
	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
1079 1080 1081 1082

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

1086
		/* Scaling up by 1000000 as fixed decimal */
I
Ian McDonald 已提交
1087 1088
		if (i_mean != 0)
			hcrx->ccid3hcrx_p = 1000000 / i_mean;
I
Ian McDonald 已提交
1089 1090 1091
	} else {
		printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__);
		dump_stack();
I
Ian McDonald 已提交
1092
	}
1093 1094 1095 1096 1097 1098 1099

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

1100
static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
1101 1102
{
	struct dccp_sock *dp = dccp_sk(sk);
1103
	struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
1104 1105 1106

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

1107 1108 1109
	if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE &&
	    dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE)
		hcrx->ccid3hcrx_s = dp->dccps_packet_size;
1110 1111 1112 1113 1114
	else
		hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;

	hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
1115
	INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist);
1116
	dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack);
1117 1118
	hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack;
	hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */
1119 1120 1121 1122 1123
	return 0;
}

static void ccid3_hc_rx_exit(struct sock *sk)
{
1124
	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1125

1126
	BUG_ON(hcrx == NULL);
1127 1128 1129 1130

	ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);

	/* Empty packet history */
1131
	dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
1132 1133

	/* Empty loss interval history */
1134
	dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
1135 1136
}

1137 1138
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
{
1139
	const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
1140

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

1145
	BUG_ON(hcrx == NULL);
1146 1147 1148 1149 1150 1151 1152 1153

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

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

1160
	BUG_ON(hctx == NULL);
1161 1162 1163 1164 1165

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

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 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
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;
}

1220
static struct ccid_operations ccid3 = {
I
Ian McDonald 已提交
1221
	.ccid_id		   = DCCPC_CCID3,
1222 1223
	.ccid_name		   = "ccid3",
	.ccid_owner		   = THIS_MODULE,
1224
	.ccid_hc_tx_obj_size	   = sizeof(struct ccid3_hc_tx_sock),
1225 1226 1227 1228 1229 1230 1231
	.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,
1232
	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
1233 1234 1235 1236
	.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,
1237 1238
	.ccid_hc_rx_get_info	   = ccid3_hc_rx_get_info,
	.ccid_hc_tx_get_info	   = ccid3_hc_tx_get_info,
1239 1240
	.ccid_hc_rx_getsockopt	   = ccid3_hc_rx_getsockopt,
	.ccid_hc_tx_getsockopt	   = ccid3_hc_tx_getsockopt,
1241 1242 1243 1244 1245 1246 1247
};
 
module_param(ccid3_debug, int, 0444);
MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");

static __init int ccid3_module_init(void)
{
1248
	int rc = -ENOBUFS;
1249

1250 1251
	ccid3_rx_hist = dccp_rx_hist_new("ccid3");
	if (ccid3_rx_hist == NULL)
1252 1253
		goto out;

1254 1255 1256
	ccid3_tx_hist = dccp_tx_hist_new("ccid3");
	if (ccid3_tx_hist == NULL)
		goto out_free_rx;
1257

1258 1259
	ccid3_li_hist = dccp_li_hist_new("ccid3");
	if (ccid3_li_hist == NULL)
1260
		goto out_free_tx;
1261 1262 1263 1264 1265 1266

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

1268
out_free_loss_interval_history:
1269 1270
	dccp_li_hist_delete(ccid3_li_hist);
	ccid3_li_hist = NULL;
1271 1272 1273 1274 1275 1276
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;
1277 1278 1279 1280 1281 1282 1283 1284
	goto out;
}
module_init(ccid3_module_init);

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

1285 1286 1287
	if (ccid3_tx_hist != NULL) {
		dccp_tx_hist_delete(ccid3_tx_hist);
		ccid3_tx_hist = NULL;
1288
	}
1289 1290 1291
	if (ccid3_rx_hist != NULL) {
		dccp_rx_hist_delete(ccid3_rx_hist);
		ccid3_rx_hist = NULL;
1292
	}
1293 1294 1295
	if (ccid3_li_hist != NULL) {
		dccp_li_hist_delete(ccid3_li_hist);
		ccid3_li_hist = NULL;
1296 1297 1298 1299
	}
}
module_exit(ccid3_module_exit);

1300
MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1301
	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1302 1303 1304
MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
MODULE_LICENSE("GPL");
MODULE_ALIAS("net-dccp-ccid-3");