1 /* 2 * net/dccp/ccids/ccid3.c 3 * 4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 5 * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com> 6 * 7 * An implementation of the DCCP protocol 8 * 9 * This code has been developed by the University of Waikato WAND 10 * research group. For further information please see http://www.wand.net.nz/ 11 * 12 * This code also uses code from Lulea University, rereleased as GPL by its 13 * authors: 14 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon 15 * 16 * Changes to meet Linux coding standards, to make it meet latest ccid3 draft 17 * and to make it work as a loadable module in the DCCP stack written by 18 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>. 19 * 20 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 21 * 22 * This program is free software; you can redistribute it and/or modify 23 * it under the terms of the GNU General Public License as published by 24 * the Free Software Foundation; either version 2 of the License, or 25 * (at your option) any later version. 26 * 27 * This program is distributed in the hope that it will be useful, 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * GNU General Public License for more details. 31 * 32 * You should have received a copy of the GNU General Public License 33 * along with this program; if not, write to the Free Software 34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 35 */ 36 37 #include <linux/config.h> 38 #include "../ccid.h" 39 #include "../dccp.h" 40 #include "lib/packet_history.h" 41 #include "lib/loss_interval.h" 42 #include "lib/tfrc.h" 43 #include "ccid3.h" 44 45 /* 46 * Reason for maths here is to avoid 32 bit overflow when a is big. 47 * With this we get close to the limit. 48 */ 49 static u32 usecs_div(const u32 a, const u32 b) 50 { 51 const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 : 52 a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 : 53 a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 : 54 a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 : 55 a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 : 56 a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 : 57 a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 : 58 a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 : 59 100000; 60 const u32 tmp = a * (USEC_PER_SEC / div); 61 return (b >= 2 * div) ? tmp / (b / div) : tmp; 62 } 63 64 static int ccid3_debug; 65 66 #ifdef CCID3_DEBUG 67 #define ccid3_pr_debug(format, a...) \ 68 do { if (ccid3_debug) \ 69 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ 70 } while (0) 71 #else 72 #define ccid3_pr_debug(format, a...) 73 #endif 74 75 static struct dccp_tx_hist *ccid3_tx_hist; 76 static struct dccp_rx_hist *ccid3_rx_hist; 77 static struct dccp_li_hist *ccid3_li_hist; 78 79 /* TFRC sender states */ 80 enum ccid3_hc_tx_states { 81 TFRC_SSTATE_NO_SENT = 1, 82 TFRC_SSTATE_NO_FBACK, 83 TFRC_SSTATE_FBACK, 84 TFRC_SSTATE_TERM, 85 }; 86 87 #ifdef CCID3_DEBUG 88 static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) 89 { 90 static char *ccid3_state_names[] = { 91 [TFRC_SSTATE_NO_SENT] = "NO_SENT", 92 [TFRC_SSTATE_NO_FBACK] = "NO_FBACK", 93 [TFRC_SSTATE_FBACK] = "FBACK", 94 [TFRC_SSTATE_TERM] = "TERM", 95 }; 96 97 return ccid3_state_names[state]; 98 } 99 #endif 100 101 static void ccid3_hc_tx_set_state(struct sock *sk, 102 enum ccid3_hc_tx_states state) 103 { 104 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 105 enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state; 106 107 ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", 108 dccp_role(sk), sk, ccid3_tx_state_name(oldstate), 109 ccid3_tx_state_name(state)); 110 WARN_ON(state == oldstate); 111 hctx->ccid3hctx_state = state; 112 } 113 114 /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ 115 static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) 116 { 117 /* 118 * If no feedback spec says t_ipi is 1 second (set elsewhere and then 119 * doubles after every no feedback timer (separate function) 120 */ 121 if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK) 122 hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s, 123 hctx->ccid3hctx_x); 124 } 125 126 /* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ 127 static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) 128 { 129 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, 130 TFRC_OPSYS_HALF_TIME_GRAN); 131 } 132 133 /* 134 * Update X by 135 * If (p > 0) 136 * x_calc = calcX(s, R, p); 137 * X = max(min(X_calc, 2 * X_recv), s / t_mbi); 138 * Else 139 * If (now - tld >= R) 140 * X = max(min(2 * X, 2 * X_recv), s / R); 141 * tld = now; 142 */ 143 static void ccid3_hc_tx_update_x(struct sock *sk) 144 { 145 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 146 147 /* To avoid large error in calcX */ 148 if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { 149 hctx->ccid3hctx_x_calc = tfrc_calc_x(hctx->ccid3hctx_s, 150 hctx->ccid3hctx_rtt, 151 hctx->ccid3hctx_p); 152 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc, 153 2 * hctx->ccid3hctx_x_recv), 154 (hctx->ccid3hctx_s / 155 TFRC_MAX_BACK_OFF_TIME)); 156 } else { 157 struct timeval now; 158 159 dccp_timestamp(sk, &now); 160 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= 161 hctx->ccid3hctx_rtt) { 162 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, 163 hctx->ccid3hctx_x) * 2, 164 usecs_div(hctx->ccid3hctx_s, 165 hctx->ccid3hctx_rtt)); 166 hctx->ccid3hctx_t_ld = now; 167 } 168 } 169 } 170 171 static void ccid3_hc_tx_no_feedback_timer(unsigned long data) 172 { 173 struct sock *sk = (struct sock *)data; 174 unsigned long next_tmout = 0; 175 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 176 177 bh_lock_sock(sk); 178 if (sock_owned_by_user(sk)) { 179 /* Try again later. */ 180 /* XXX: set some sensible MIB */ 181 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 182 jiffies + HZ / 5); 183 goto out; 184 } 185 186 ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, 187 ccid3_tx_state_name(hctx->ccid3hctx_state)); 188 189 switch (hctx->ccid3hctx_state) { 190 case TFRC_SSTATE_TERM: 191 goto out; 192 case TFRC_SSTATE_NO_FBACK: 193 /* Halve send rate */ 194 hctx->ccid3hctx_x /= 2; 195 if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s / 196 TFRC_MAX_BACK_OFF_TIME)) 197 hctx->ccid3hctx_x = (hctx->ccid3hctx_s / 198 TFRC_MAX_BACK_OFF_TIME); 199 200 ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d " 201 "bytes/s\n", 202 dccp_role(sk), sk, 203 ccid3_tx_state_name(hctx->ccid3hctx_state), 204 hctx->ccid3hctx_x); 205 next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s, 206 hctx->ccid3hctx_x), 207 TFRC_INITIAL_TIMEOUT); 208 /* 209 * FIXME - not sure above calculation is correct. See section 210 * 5 of CCID3 11 should adjust tx_t_ipi and double that to 211 * achieve it really 212 */ 213 break; 214 case TFRC_SSTATE_FBACK: 215 /* 216 * Check if IDLE since last timeout and recv rate is less than 217 * 4 packets per RTT 218 */ 219 if (!hctx->ccid3hctx_idle || 220 (hctx->ccid3hctx_x_recv >= 221 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) { 222 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", 223 dccp_role(sk), sk, 224 ccid3_tx_state_name(hctx->ccid3hctx_state)); 225 /* Halve sending rate */ 226 227 /* If (X_calc > 2 * X_recv) 228 * X_recv = max(X_recv / 2, s / (2 * t_mbi)); 229 * Else 230 * X_recv = X_calc / 4; 231 */ 232 BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P && 233 hctx->ccid3hctx_x_calc == 0); 234 235 /* check also if p is zero -> x_calc is infinity? */ 236 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P || 237 hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv) 238 hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2, 239 hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME)); 240 else 241 hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4; 242 243 /* Update sending rate */ 244 ccid3_hc_tx_update_x(sk); 245 } 246 /* 247 * Schedule no feedback timer to expire in 248 * max(4 * R, 2 * s / X) 249 */ 250 next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, 251 2 * usecs_div(hctx->ccid3hctx_s, 252 hctx->ccid3hctx_x)); 253 break; 254 default: 255 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 256 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); 257 dump_stack(); 258 goto out; 259 } 260 261 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 262 jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); 263 hctx->ccid3hctx_idle = 1; 264 out: 265 bh_unlock_sock(sk); 266 sock_put(sk); 267 } 268 269 static int ccid3_hc_tx_send_packet(struct sock *sk, 270 struct sk_buff *skb, int len) 271 { 272 struct dccp_sock *dp = dccp_sk(sk); 273 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 274 struct dccp_tx_hist_entry *new_packet; 275 struct timeval now; 276 long delay; 277 int rc = -ENOTCONN; 278 279 BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); 280 281 /* Check if pure ACK or Terminating*/ 282 /* 283 * XXX: We only call this function for DATA and DATAACK, on, these 284 * packets can have zero length, but why the comment about "pure ACK"? 285 */ 286 if (unlikely(len == 0)) 287 goto out; 288 289 /* See if last packet allocated was not sent */ 290 new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); 291 if (new_packet == NULL || new_packet->dccphtx_sent) { 292 new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, 293 SLAB_ATOMIC); 294 295 rc = -ENOBUFS; 296 if (unlikely(new_packet == NULL)) { 297 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough " 298 "mem to add to history, send refused\n", 299 __FUNCTION__, dccp_role(sk), sk); 300 goto out; 301 } 302 303 dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); 304 } 305 306 dccp_timestamp(sk, &now); 307 308 switch (hctx->ccid3hctx_state) { 309 case TFRC_SSTATE_NO_SENT: 310 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 311 jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT)); 312 hctx->ccid3hctx_last_win_count = 0; 313 hctx->ccid3hctx_t_last_win_count = now; 314 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); 315 hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI; 316 317 /* Set nominal send time for initial packet */ 318 hctx->ccid3hctx_t_nom = now; 319 timeval_add_usecs(&hctx->ccid3hctx_t_nom, 320 hctx->ccid3hctx_t_ipi); 321 ccid3_calc_new_delta(hctx); 322 rc = 0; 323 break; 324 case TFRC_SSTATE_NO_FBACK: 325 case TFRC_SSTATE_FBACK: 326 delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - 327 hctx->ccid3hctx_delta); 328 delay /= -1000; 329 /* divide by -1000 is to convert to ms and get sign right */ 330 rc = delay > 0 ? delay : 0; 331 break; 332 default: 333 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 334 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); 335 dump_stack(); 336 rc = -EINVAL; 337 break; 338 } 339 340 /* Can we send? if so add options and add to packet history */ 341 if (rc == 0) { 342 dp->dccps_hc_tx_insert_options = 1; 343 new_packet->dccphtx_ccval = 344 DCCP_SKB_CB(skb)->dccpd_ccval = 345 hctx->ccid3hctx_last_win_count; 346 } 347 out: 348 return rc; 349 } 350 351 static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) 352 { 353 const struct dccp_sock *dp = dccp_sk(sk); 354 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 355 struct timeval now; 356 357 BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); 358 359 dccp_timestamp(sk, &now); 360 361 /* check if we have sent a data packet */ 362 if (len > 0) { 363 unsigned long quarter_rtt; 364 struct dccp_tx_hist_entry *packet; 365 366 packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); 367 if (unlikely(packet == NULL)) { 368 LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't " 369 "exists in history!\n", __FUNCTION__); 370 return; 371 } 372 if (unlikely(packet->dccphtx_sent)) { 373 LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in " 374 "history!\n", __FUNCTION__); 375 return; 376 } 377 packet->dccphtx_tstamp = now; 378 packet->dccphtx_seqno = dp->dccps_gss; 379 /* 380 * Check if win_count have changed 381 * Algorithm in "8.1. Window Counter Valuer" in 382 * draft-ietf-dccp-ccid3-11.txt 383 */ 384 quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count); 385 if (likely(hctx->ccid3hctx_rtt > 8)) 386 quarter_rtt /= hctx->ccid3hctx_rtt / 4; 387 388 if (quarter_rtt > 0) { 389 hctx->ccid3hctx_t_last_win_count = now; 390 hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + 391 min_t(unsigned long, quarter_rtt, 5)) % 16; 392 ccid3_pr_debug("%s, sk=%p, window changed from " 393 "%u to %u!\n", 394 dccp_role(sk), sk, 395 packet->dccphtx_ccval, 396 hctx->ccid3hctx_last_win_count); 397 } 398 399 hctx->ccid3hctx_idle = 0; 400 packet->dccphtx_rtt = hctx->ccid3hctx_rtt; 401 packet->dccphtx_sent = 1; 402 } else 403 ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", 404 dccp_role(sk), sk, dp->dccps_gss); 405 406 switch (hctx->ccid3hctx_state) { 407 case TFRC_SSTATE_NO_SENT: 408 /* if first wasn't pure ack */ 409 if (len != 0) 410 printk(KERN_CRIT "%s: %s, First packet sent is noted " 411 "as a data packet\n", 412 __FUNCTION__, dccp_role(sk)); 413 return; 414 case TFRC_SSTATE_NO_FBACK: 415 case TFRC_SSTATE_FBACK: 416 if (len > 0) { 417 hctx->ccid3hctx_t_nom = now; 418 ccid3_calc_new_t_ipi(hctx); 419 ccid3_calc_new_delta(hctx); 420 timeval_add_usecs(&hctx->ccid3hctx_t_nom, 421 hctx->ccid3hctx_t_ipi); 422 } 423 break; 424 default: 425 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 426 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); 427 dump_stack(); 428 break; 429 } 430 } 431 432 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) 433 { 434 const struct dccp_sock *dp = dccp_sk(sk); 435 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 436 struct ccid3_options_received *opt_recv; 437 struct dccp_tx_hist_entry *packet; 438 struct timeval now; 439 unsigned long next_tmout; 440 u32 t_elapsed; 441 u32 pinv; 442 u32 x_recv; 443 u32 r_sample; 444 445 BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); 446 447 /* we are only interested in ACKs */ 448 if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || 449 DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) 450 return; 451 452 opt_recv = &hctx->ccid3hctx_options_received; 453 454 t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; 455 x_recv = opt_recv->ccid3or_receive_rate; 456 pinv = opt_recv->ccid3or_loss_event_rate; 457 458 switch (hctx->ccid3hctx_state) { 459 case TFRC_SSTATE_NO_SENT: 460 /* FIXME: what to do here? */ 461 return; 462 case TFRC_SSTATE_NO_FBACK: 463 case TFRC_SSTATE_FBACK: 464 /* Calculate new round trip sample by 465 * R_sample = (now - t_recvdata) - t_delay */ 466 /* get t_recvdata from history */ 467 packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, 468 DCCP_SKB_CB(skb)->dccpd_ack_seq); 469 if (unlikely(packet == NULL)) { 470 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno " 471 "%llu(%s) does't exist in history!\n", 472 __FUNCTION__, dccp_role(sk), sk, 473 (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, 474 dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); 475 return; 476 } 477 478 /* Update RTT */ 479 dccp_timestamp(sk, &now); 480 r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); 481 if (unlikely(r_sample <= t_elapsed)) 482 LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " 483 "t_elapsed=%uus\n", 484 __FUNCTION__, r_sample, t_elapsed); 485 else 486 r_sample -= t_elapsed; 487 488 /* Update RTT estimate by 489 * If (No feedback recv) 490 * R = R_sample; 491 * Else 492 * R = q * R + (1 - q) * R_sample; 493 * 494 * q is a constant, RFC 3448 recomments 0.9 495 */ 496 if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { 497 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); 498 hctx->ccid3hctx_rtt = r_sample; 499 } else 500 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + 501 r_sample / 10; 502 503 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " 504 "r_sample=%us\n", dccp_role(sk), sk, 505 hctx->ccid3hctx_rtt, r_sample); 506 507 /* Update timeout interval */ 508 hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, 509 USEC_PER_SEC); 510 511 /* Update receive rate */ 512 hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ 513 514 /* Update loss event rate */ 515 if (pinv == ~0 || pinv == 0) 516 hctx->ccid3hctx_p = 0; 517 else { 518 hctx->ccid3hctx_p = 1000000 / pinv; 519 520 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) { 521 hctx->ccid3hctx_p = TFRC_SMALLEST_P; 522 ccid3_pr_debug("%s, sk=%p, Smallest p used!\n", 523 dccp_role(sk), sk); 524 } 525 } 526 527 /* unschedule no feedback timer */ 528 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); 529 530 /* Update sending rate */ 531 ccid3_hc_tx_update_x(sk); 532 533 /* Update next send time */ 534 timeval_sub_usecs(&hctx->ccid3hctx_t_nom, 535 hctx->ccid3hctx_t_ipi); 536 ccid3_calc_new_t_ipi(hctx); 537 timeval_add_usecs(&hctx->ccid3hctx_t_nom, 538 hctx->ccid3hctx_t_ipi); 539 ccid3_calc_new_delta(hctx); 540 541 /* remove all packets older than the one acked from history */ 542 dccp_tx_hist_purge_older(ccid3_tx_hist, 543 &hctx->ccid3hctx_hist, packet); 544 /* 545 * As we have calculated new ipi, delta, t_nom it is possible that 546 * we now can send a packet, so wake up dccp_wait_for_ccids. 547 */ 548 sk->sk_write_space(sk); 549 550 /* 551 * Schedule no feedback timer to expire in 552 * max(4 * R, 2 * s / X) 553 */ 554 next_tmout = max(hctx->ccid3hctx_t_rto, 555 2 * usecs_div(hctx->ccid3hctx_s, 556 hctx->ccid3hctx_x)); 557 558 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " 559 "expire in %lu jiffies (%luus)\n", 560 dccp_role(sk), sk, 561 usecs_to_jiffies(next_tmout), next_tmout); 562 563 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, 564 jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); 565 566 /* set idle flag */ 567 hctx->ccid3hctx_idle = 1; 568 break; 569 default: 570 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 571 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); 572 dump_stack(); 573 break; 574 } 575 } 576 577 static int ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) 578 { 579 const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 580 581 BUG_ON(hctx == NULL); 582 583 if (sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN) 584 DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; 585 return 0; 586 } 587 588 static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, 589 unsigned char len, u16 idx, 590 unsigned char *value) 591 { 592 int rc = 0; 593 const struct dccp_sock *dp = dccp_sk(sk); 594 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 595 struct ccid3_options_received *opt_recv; 596 597 BUG_ON(hctx == NULL); 598 599 opt_recv = &hctx->ccid3hctx_options_received; 600 601 if (opt_recv->ccid3or_seqno != dp->dccps_gsr) { 602 opt_recv->ccid3or_seqno = dp->dccps_gsr; 603 opt_recv->ccid3or_loss_event_rate = ~0; 604 opt_recv->ccid3or_loss_intervals_idx = 0; 605 opt_recv->ccid3or_loss_intervals_len = 0; 606 opt_recv->ccid3or_receive_rate = 0; 607 } 608 609 switch (option) { 610 case TFRC_OPT_LOSS_EVENT_RATE: 611 if (unlikely(len != 4)) { 612 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " 613 "len for TFRC_OPT_LOSS_EVENT_RATE\n", 614 __FUNCTION__, dccp_role(sk), sk); 615 rc = -EINVAL; 616 } else { 617 opt_recv->ccid3or_loss_event_rate = ntohl(*(__be32 *)value); 618 ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", 619 dccp_role(sk), sk, 620 opt_recv->ccid3or_loss_event_rate); 621 } 622 break; 623 case TFRC_OPT_LOSS_INTERVALS: 624 opt_recv->ccid3or_loss_intervals_idx = idx; 625 opt_recv->ccid3or_loss_intervals_len = len; 626 ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n", 627 dccp_role(sk), sk, 628 opt_recv->ccid3or_loss_intervals_idx, 629 opt_recv->ccid3or_loss_intervals_len); 630 break; 631 case TFRC_OPT_RECEIVE_RATE: 632 if (unlikely(len != 4)) { 633 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " 634 "len for TFRC_OPT_RECEIVE_RATE\n", 635 __FUNCTION__, dccp_role(sk), sk); 636 rc = -EINVAL; 637 } else { 638 opt_recv->ccid3or_receive_rate = ntohl(*(__be32 *)value); 639 ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", 640 dccp_role(sk), sk, 641 opt_recv->ccid3or_receive_rate); 642 } 643 break; 644 } 645 646 return rc; 647 } 648 649 static int ccid3_hc_tx_init(struct ccid *ccid, struct sock *sk) 650 { 651 struct dccp_sock *dp = dccp_sk(sk); 652 struct ccid3_hc_tx_sock *hctx = ccid_priv(ccid); 653 654 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 655 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) 656 hctx->ccid3hctx_s = dp->dccps_packet_size; 657 else 658 hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE; 659 660 /* Set transmission rate to 1 packet per second */ 661 hctx->ccid3hctx_x = hctx->ccid3hctx_s; 662 hctx->ccid3hctx_t_rto = USEC_PER_SEC; 663 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; 664 INIT_LIST_HEAD(&hctx->ccid3hctx_hist); 665 666 hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer; 667 hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk; 668 init_timer(&hctx->ccid3hctx_no_feedback_timer); 669 670 return 0; 671 } 672 673 static void ccid3_hc_tx_exit(struct sock *sk) 674 { 675 struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 676 677 BUG_ON(hctx == NULL); 678 679 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); 680 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); 681 682 /* Empty packet history */ 683 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); 684 } 685 686 /* 687 * RX Half Connection methods 688 */ 689 690 /* TFRC receiver states */ 691 enum ccid3_hc_rx_states { 692 TFRC_RSTATE_NO_DATA = 1, 693 TFRC_RSTATE_DATA, 694 TFRC_RSTATE_TERM = 127, 695 }; 696 697 #ifdef CCID3_DEBUG 698 static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) 699 { 700 static char *ccid3_rx_state_names[] = { 701 [TFRC_RSTATE_NO_DATA] = "NO_DATA", 702 [TFRC_RSTATE_DATA] = "DATA", 703 [TFRC_RSTATE_TERM] = "TERM", 704 }; 705 706 return ccid3_rx_state_names[state]; 707 } 708 #endif 709 710 static void ccid3_hc_rx_set_state(struct sock *sk, 711 enum ccid3_hc_rx_states state) 712 { 713 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 714 enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state; 715 716 ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", 717 dccp_role(sk), sk, ccid3_rx_state_name(oldstate), 718 ccid3_rx_state_name(state)); 719 WARN_ON(state == oldstate); 720 hcrx->ccid3hcrx_state = state; 721 } 722 723 static void ccid3_hc_rx_send_feedback(struct sock *sk) 724 { 725 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 726 struct dccp_sock *dp = dccp_sk(sk); 727 struct dccp_rx_hist_entry *packet; 728 struct timeval now; 729 730 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 731 732 dccp_timestamp(sk, &now); 733 734 switch (hcrx->ccid3hcrx_state) { 735 case TFRC_RSTATE_NO_DATA: 736 hcrx->ccid3hcrx_x_recv = 0; 737 break; 738 case TFRC_RSTATE_DATA: { 739 const u32 delta = timeval_delta(&now, 740 &hcrx->ccid3hcrx_tstamp_last_feedback); 741 hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, 742 delta); 743 } 744 break; 745 default: 746 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 747 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); 748 dump_stack(); 749 return; 750 } 751 752 packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); 753 if (unlikely(packet == NULL)) { 754 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " 755 "in history!\n", 756 __FUNCTION__, dccp_role(sk), sk); 757 return; 758 } 759 760 hcrx->ccid3hcrx_tstamp_last_feedback = now; 761 hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; 762 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; 763 hcrx->ccid3hcrx_bytes_recv = 0; 764 765 /* Convert to multiples of 10us */ 766 hcrx->ccid3hcrx_elapsed_time = 767 timeval_delta(&now, &packet->dccphrx_tstamp) / 10; 768 if (hcrx->ccid3hcrx_p == 0) 769 hcrx->ccid3hcrx_pinv = ~0; 770 else 771 hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; 772 dp->dccps_hc_rx_insert_options = 1; 773 dccp_send_ack(sk); 774 } 775 776 static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) 777 { 778 const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 779 __be32 x_recv, pinv; 780 781 BUG_ON(hcrx == NULL); 782 783 if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) 784 return 0; 785 786 DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; 787 788 if (dccp_packet_without_ack(skb)) 789 return 0; 790 791 x_recv = htonl(hcrx->ccid3hcrx_x_recv); 792 pinv = htonl(hcrx->ccid3hcrx_pinv); 793 794 if ((hcrx->ccid3hcrx_elapsed_time != 0 && 795 dccp_insert_option_elapsed_time(sk, skb, 796 hcrx->ccid3hcrx_elapsed_time)) || 797 dccp_insert_option_timestamp(sk, skb) || 798 dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, 799 &pinv, sizeof(pinv)) || 800 dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, 801 &x_recv, sizeof(x_recv))) 802 return -1; 803 804 return 0; 805 } 806 807 /* calculate first loss interval 808 * 809 * returns estimated loss interval in usecs */ 810 811 static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) 812 { 813 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 814 struct dccp_rx_hist_entry *entry, *next, *tail = NULL; 815 u32 rtt, delta, x_recv, fval, p, tmp2; 816 struct timeval tstamp = { 0, }; 817 int interval = 0; 818 int win_count = 0; 819 int step = 0; 820 u64 tmp1; 821 822 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, 823 dccphrx_node) { 824 if (dccp_rx_hist_entry_data_packet(entry)) { 825 tail = entry; 826 827 switch (step) { 828 case 0: 829 tstamp = entry->dccphrx_tstamp; 830 win_count = entry->dccphrx_ccval; 831 step = 1; 832 break; 833 case 1: 834 interval = win_count - entry->dccphrx_ccval; 835 if (interval < 0) 836 interval += TFRC_WIN_COUNT_LIMIT; 837 if (interval > 4) 838 goto found; 839 break; 840 } 841 } 842 } 843 844 if (unlikely(step == 0)) { 845 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history " 846 "contains no data packets!\n", 847 __FUNCTION__, dccp_role(sk), sk); 848 return ~0; 849 } 850 851 if (unlikely(interval == 0)) { 852 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a " 853 "win_count interval > 0. Defaulting to 1\n", 854 __FUNCTION__, dccp_role(sk), sk); 855 interval = 1; 856 } 857 found: 858 rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; 859 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", 860 dccp_role(sk), sk, rtt); 861 if (rtt == 0) 862 rtt = 1; 863 864 dccp_timestamp(sk, &tstamp); 865 delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); 866 x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); 867 868 tmp1 = (u64)x_recv * (u64)rtt; 869 do_div(tmp1,10000000); 870 tmp2 = (u32)tmp1; 871 fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; 872 /* do not alter order above or you will get overflow on 32 bit */ 873 p = tfrc_calc_x_reverse_lookup(fval); 874 ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied " 875 "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); 876 877 if (p == 0) 878 return ~0; 879 else 880 return 1000000 / p; 881 } 882 883 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) 884 { 885 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 886 887 if (seq_loss != DCCP_MAX_SEQNO + 1 && 888 list_empty(&hcrx->ccid3hcrx_li_hist)) { 889 struct dccp_li_hist_entry *li_tail; 890 891 li_tail = dccp_li_hist_interval_new(ccid3_li_hist, 892 &hcrx->ccid3hcrx_li_hist, 893 seq_loss, win_loss); 894 if (li_tail == NULL) 895 return; 896 li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); 897 } else 898 LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of " 899 "interval\n", __FUNCTION__); 900 } 901 902 static void ccid3_hc_rx_detect_loss(struct sock *sk) 903 { 904 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 905 u8 win_loss; 906 const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, 907 &hcrx->ccid3hcrx_li_hist, 908 &win_loss); 909 910 ccid3_hc_rx_update_li(sk, seq_loss, win_loss); 911 } 912 913 static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 914 { 915 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 916 const struct dccp_options_received *opt_recv; 917 struct dccp_rx_hist_entry *packet; 918 struct timeval now; 919 u8 win_count; 920 u32 p_prev, r_sample, t_elapsed; 921 int ins; 922 923 BUG_ON(hcrx == NULL || 924 !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || 925 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA)); 926 927 opt_recv = &dccp_sk(sk)->dccps_options_received; 928 929 switch (DCCP_SKB_CB(skb)->dccpd_type) { 930 case DCCP_PKT_ACK: 931 if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA) 932 return; 933 case DCCP_PKT_DATAACK: 934 if (opt_recv->dccpor_timestamp_echo == 0) 935 break; 936 p_prev = hcrx->ccid3hcrx_rtt; 937 dccp_timestamp(sk, &now); 938 timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); 939 r_sample = timeval_usecs(&now); 940 t_elapsed = opt_recv->dccpor_elapsed_time * 10; 941 942 if (unlikely(r_sample <= t_elapsed)) 943 LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " 944 "t_elapsed=%uus\n", 945 __FUNCTION__, r_sample, t_elapsed); 946 else 947 r_sample -= t_elapsed; 948 949 if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA) 950 hcrx->ccid3hcrx_rtt = r_sample; 951 else 952 hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + 953 r_sample / 10; 954 955 if (p_prev != hcrx->ccid3hcrx_rtt) 956 ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", 957 dccp_role(sk), hcrx->ccid3hcrx_rtt, 958 opt_recv->dccpor_elapsed_time); 959 break; 960 case DCCP_PKT_DATA: 961 break; 962 default: /* We're not interested in other packet types, move along */ 963 return; 964 } 965 966 packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, 967 skb, SLAB_ATOMIC); 968 if (unlikely(packet == NULL)) { 969 LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to " 970 "add rx packet to history, consider it lost!\n", 971 __FUNCTION__, dccp_role(sk), sk); 972 return; 973 } 974 975 win_count = packet->dccphrx_ccval; 976 977 ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, 978 &hcrx->ccid3hcrx_li_hist, packet); 979 980 if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) 981 return; 982 983 switch (hcrx->ccid3hcrx_state) { 984 case TFRC_RSTATE_NO_DATA: 985 ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial " 986 "feedback\n", 987 dccp_role(sk), sk, 988 dccp_state_name(sk->sk_state), skb); 989 ccid3_hc_rx_send_feedback(sk); 990 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA); 991 return; 992 case TFRC_RSTATE_DATA: 993 hcrx->ccid3hcrx_bytes_recv += skb->len - 994 dccp_hdr(skb)->dccph_doff * 4; 995 if (ins != 0) 996 break; 997 998 dccp_timestamp(sk, &now); 999 if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >= 1000 hcrx->ccid3hcrx_rtt) { 1001 hcrx->ccid3hcrx_tstamp_last_ack = now; 1002 ccid3_hc_rx_send_feedback(sk); 1003 } 1004 return; 1005 default: 1006 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 1007 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); 1008 dump_stack(); 1009 return; 1010 } 1011 1012 /* Dealing with packet loss */ 1013 ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", 1014 dccp_role(sk), sk, dccp_state_name(sk->sk_state)); 1015 1016 ccid3_hc_rx_detect_loss(sk); 1017 p_prev = hcrx->ccid3hcrx_p; 1018 1019 /* Calculate loss event rate */ 1020 if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { 1021 u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); 1022 1023 /* Scaling up by 1000000 as fixed decimal */ 1024 if (i_mean != 0) 1025 hcrx->ccid3hcrx_p = 1000000 / i_mean; 1026 } 1027 1028 if (hcrx->ccid3hcrx_p > p_prev) { 1029 ccid3_hc_rx_send_feedback(sk); 1030 return; 1031 } 1032 } 1033 1034 static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) 1035 { 1036 struct dccp_sock *dp = dccp_sk(sk); 1037 struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); 1038 1039 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1040 1041 if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && 1042 dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) 1043 hcrx->ccid3hcrx_s = dp->dccps_packet_size; 1044 else 1045 hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE; 1046 1047 hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; 1048 INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); 1049 INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); 1050 dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); 1051 hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; 1052 hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ 1053 return 0; 1054 } 1055 1056 static void ccid3_hc_rx_exit(struct sock *sk) 1057 { 1058 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 1059 1060 BUG_ON(hcrx == NULL); 1061 1062 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM); 1063 1064 /* Empty packet history */ 1065 dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); 1066 1067 /* Empty loss interval history */ 1068 dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); 1069 } 1070 1071 static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) 1072 { 1073 const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 1074 1075 /* Listen socks doesn't have a private CCID block */ 1076 if (sk->sk_state == DCCP_LISTEN) 1077 return; 1078 1079 BUG_ON(hcrx == NULL); 1080 1081 info->tcpi_ca_state = hcrx->ccid3hcrx_state; 1082 info->tcpi_options |= TCPI_OPT_TIMESTAMPS; 1083 info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt; 1084 } 1085 1086 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) 1087 { 1088 const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 1089 1090 /* Listen socks doesn't have a private CCID block */ 1091 if (sk->sk_state == DCCP_LISTEN) 1092 return; 1093 1094 BUG_ON(hctx == NULL); 1095 1096 info->tcpi_rto = hctx->ccid3hctx_t_rto; 1097 info->tcpi_rtt = hctx->ccid3hctx_rtt; 1098 } 1099 1100 static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, 1101 u32 __user *optval, int __user *optlen) 1102 { 1103 const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 1104 const void *val; 1105 1106 /* Listen socks doesn't have a private CCID block */ 1107 if (sk->sk_state == DCCP_LISTEN) 1108 return -EINVAL; 1109 1110 switch (optname) { 1111 case DCCP_SOCKOPT_CCID_RX_INFO: 1112 if (len < sizeof(hcrx->ccid3hcrx_tfrc)) 1113 return -EINVAL; 1114 len = sizeof(hcrx->ccid3hcrx_tfrc); 1115 val = &hcrx->ccid3hcrx_tfrc; 1116 break; 1117 default: 1118 return -ENOPROTOOPT; 1119 } 1120 1121 if (put_user(len, optlen) || copy_to_user(optval, val, len)) 1122 return -EFAULT; 1123 1124 return 0; 1125 } 1126 1127 static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, 1128 u32 __user *optval, int __user *optlen) 1129 { 1130 const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); 1131 const void *val; 1132 1133 /* Listen socks doesn't have a private CCID block */ 1134 if (sk->sk_state == DCCP_LISTEN) 1135 return -EINVAL; 1136 1137 switch (optname) { 1138 case DCCP_SOCKOPT_CCID_TX_INFO: 1139 if (len < sizeof(hctx->ccid3hctx_tfrc)) 1140 return -EINVAL; 1141 len = sizeof(hctx->ccid3hctx_tfrc); 1142 val = &hctx->ccid3hctx_tfrc; 1143 break; 1144 default: 1145 return -ENOPROTOOPT; 1146 } 1147 1148 if (put_user(len, optlen) || copy_to_user(optval, val, len)) 1149 return -EFAULT; 1150 1151 return 0; 1152 } 1153 1154 static struct ccid_operations ccid3 = { 1155 .ccid_id = 3, 1156 .ccid_name = "ccid3", 1157 .ccid_owner = THIS_MODULE, 1158 .ccid_hc_tx_obj_size = sizeof(struct ccid3_hc_tx_sock), 1159 .ccid_hc_tx_init = ccid3_hc_tx_init, 1160 .ccid_hc_tx_exit = ccid3_hc_tx_exit, 1161 .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet, 1162 .ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent, 1163 .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv, 1164 .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options, 1165 .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options, 1166 .ccid_hc_rx_obj_size = sizeof(struct ccid3_hc_rx_sock), 1167 .ccid_hc_rx_init = ccid3_hc_rx_init, 1168 .ccid_hc_rx_exit = ccid3_hc_rx_exit, 1169 .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options, 1170 .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, 1171 .ccid_hc_rx_get_info = ccid3_hc_rx_get_info, 1172 .ccid_hc_tx_get_info = ccid3_hc_tx_get_info, 1173 .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, 1174 .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, 1175 }; 1176 1177 module_param(ccid3_debug, int, 0444); 1178 MODULE_PARM_DESC(ccid3_debug, "Enable debug messages"); 1179 1180 static __init int ccid3_module_init(void) 1181 { 1182 int rc = -ENOBUFS; 1183 1184 ccid3_rx_hist = dccp_rx_hist_new("ccid3"); 1185 if (ccid3_rx_hist == NULL) 1186 goto out; 1187 1188 ccid3_tx_hist = dccp_tx_hist_new("ccid3"); 1189 if (ccid3_tx_hist == NULL) 1190 goto out_free_rx; 1191 1192 ccid3_li_hist = dccp_li_hist_new("ccid3"); 1193 if (ccid3_li_hist == NULL) 1194 goto out_free_tx; 1195 1196 rc = ccid_register(&ccid3); 1197 if (rc != 0) 1198 goto out_free_loss_interval_history; 1199 out: 1200 return rc; 1201 1202 out_free_loss_interval_history: 1203 dccp_li_hist_delete(ccid3_li_hist); 1204 ccid3_li_hist = NULL; 1205 out_free_tx: 1206 dccp_tx_hist_delete(ccid3_tx_hist); 1207 ccid3_tx_hist = NULL; 1208 out_free_rx: 1209 dccp_rx_hist_delete(ccid3_rx_hist); 1210 ccid3_rx_hist = NULL; 1211 goto out; 1212 } 1213 module_init(ccid3_module_init); 1214 1215 static __exit void ccid3_module_exit(void) 1216 { 1217 ccid_unregister(&ccid3); 1218 1219 if (ccid3_tx_hist != NULL) { 1220 dccp_tx_hist_delete(ccid3_tx_hist); 1221 ccid3_tx_hist = NULL; 1222 } 1223 if (ccid3_rx_hist != NULL) { 1224 dccp_rx_hist_delete(ccid3_rx_hist); 1225 ccid3_rx_hist = NULL; 1226 } 1227 if (ccid3_li_hist != NULL) { 1228 dccp_li_hist_delete(ccid3_li_hist); 1229 ccid3_li_hist = NULL; 1230 } 1231 } 1232 module_exit(ccid3_module_exit); 1233 1234 MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " 1235 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); 1236 MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); 1237 MODULE_LICENSE("GPL"); 1238 MODULE_ALIAS("net-dccp-ccid-3"); 1239