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