aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/associola.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r--net/sctp/associola.c93
1 files changed, 80 insertions, 13 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 525864bf4f07..8450960df24f 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -112,6 +112,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
112 asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000) 112 asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
113 * 1000; 113 * 1000;
114 asoc->frag_point = 0; 114 asoc->frag_point = 0;
115 asoc->user_frag = sp->user_frag;
115 116
116 /* Set the association max_retrans and RTO values from the 117 /* Set the association max_retrans and RTO values from the
117 * socket values. 118 * socket values.
@@ -202,6 +203,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
202 asoc->a_rwnd = asoc->rwnd; 203 asoc->a_rwnd = asoc->rwnd;
203 204
204 asoc->rwnd_over = 0; 205 asoc->rwnd_over = 0;
206 asoc->rwnd_press = 0;
205 207
206 /* Use my own max window until I learn something better. */ 208 /* Use my own max window until I learn something better. */
207 asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW; 209 asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW;
@@ -582,6 +584,33 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
582 asoc->addip_last_asconf->transport == peer) 584 asoc->addip_last_asconf->transport == peer)
583 asoc->addip_last_asconf->transport = NULL; 585 asoc->addip_last_asconf->transport = NULL;
584 586
587 /* If we have something on the transmitted list, we have to
588 * save it off. The best place is the active path.
589 */
590 if (!list_empty(&peer->transmitted)) {
591 struct sctp_transport *active = asoc->peer.active_path;
592 struct sctp_chunk *ch;
593
594 /* Reset the transport of each chunk on this list */
595 list_for_each_entry(ch, &peer->transmitted,
596 transmitted_list) {
597 ch->transport = NULL;
598 ch->rtt_in_progress = 0;
599 }
600
601 list_splice_tail_init(&peer->transmitted,
602 &active->transmitted);
603
604 /* Start a T3 timer here in case it wasn't running so
605 * that these migrated packets have a chance to get
606 * retrnasmitted.
607 */
608 if (!timer_pending(&active->T3_rtx_timer))
609 if (!mod_timer(&active->T3_rtx_timer,
610 jiffies + active->rto))
611 sctp_transport_hold(active);
612 }
613
585 asoc->peer.transport_count--; 614 asoc->peer.transport_count--;
586 615
587 sctp_transport_free(peer); 616 sctp_transport_free(peer);
@@ -651,13 +680,15 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
651 */ 680 */
652 peer->param_flags = asoc->param_flags; 681 peer->param_flags = asoc->param_flags;
653 682
683 sctp_transport_route(peer, NULL, sp);
684
654 /* Initialize the pmtu of the transport. */ 685 /* Initialize the pmtu of the transport. */
655 if (peer->param_flags & SPP_PMTUD_ENABLE) 686 if (peer->param_flags & SPP_PMTUD_DISABLE) {
656 sctp_transport_pmtu(peer); 687 if (asoc->pathmtu)
657 else if (asoc->pathmtu) 688 peer->pathmtu = asoc->pathmtu;
658 peer->pathmtu = asoc->pathmtu; 689 else
659 else 690 peer->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
660 peer->pathmtu = SCTP_DEFAULT_MAXSEGMENT; 691 }
661 692
662 /* If this is the first transport addr on this association, 693 /* If this is the first transport addr on this association,
663 * initialize the association PMTU to the peer's PMTU. 694 * initialize the association PMTU to the peer's PMTU.
@@ -673,7 +704,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
673 "%d\n", asoc, asoc->pathmtu); 704 "%d\n", asoc, asoc->pathmtu);
674 peer->pmtu_pending = 0; 705 peer->pmtu_pending = 0;
675 706
676 asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); 707 asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
677 708
678 /* The asoc->peer.port might not be meaningful yet, but 709 /* The asoc->peer.port might not be meaningful yet, but
679 * initialize the packet structure anyway. 710 * initialize the packet structure anyway.
@@ -810,11 +841,16 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
810 break; 841 break;
811 842
812 case SCTP_TRANSPORT_DOWN: 843 case SCTP_TRANSPORT_DOWN:
813 /* if the transort was never confirmed, do not transition it 844 /* If the transport was never confirmed, do not transition it
814 * to inactive state. 845 * to inactive state. Also, release the cached route since
846 * there may be a better route next time.
815 */ 847 */
816 if (transport->state != SCTP_UNCONFIRMED) 848 if (transport->state != SCTP_UNCONFIRMED)
817 transport->state = SCTP_INACTIVE; 849 transport->state = SCTP_INACTIVE;
850 else {
851 dst_release(transport->dst);
852 transport->dst = NULL;
853 }
818 854
819 spc_state = SCTP_ADDR_UNREACHABLE; 855 spc_state = SCTP_ADDR_UNREACHABLE;
820 break; 856 break;
@@ -1324,9 +1360,8 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
1324 } 1360 }
1325 1361
1326 if (pmtu) { 1362 if (pmtu) {
1327 struct sctp_sock *sp = sctp_sk(asoc->base.sk);
1328 asoc->pathmtu = pmtu; 1363 asoc->pathmtu = pmtu;
1329 asoc->frag_point = sctp_frag_point(sp, pmtu); 1364 asoc->frag_point = sctp_frag_point(asoc, pmtu);
1330 } 1365 }
1331 1366
1332 SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n", 1367 SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
@@ -1369,6 +1404,17 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
1369 asoc->rwnd += len; 1404 asoc->rwnd += len;
1370 } 1405 }
1371 1406
1407 /* If we had window pressure, start recovering it
1408 * once our rwnd had reached the accumulated pressure
1409 * threshold. The idea is to recover slowly, but up
1410 * to the initial advertised window.
1411 */
1412 if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
1413 int change = min(asoc->pathmtu, asoc->rwnd_press);
1414 asoc->rwnd += change;
1415 asoc->rwnd_press -= change;
1416 }
1417
1372 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) " 1418 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) "
1373 "- %u\n", __func__, asoc, len, asoc->rwnd, 1419 "- %u\n", __func__, asoc, len, asoc->rwnd,
1374 asoc->rwnd_over, asoc->a_rwnd); 1420 asoc->rwnd_over, asoc->a_rwnd);
@@ -1401,17 +1447,38 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
1401/* Decrease asoc's rwnd by len. */ 1447/* Decrease asoc's rwnd by len. */
1402void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) 1448void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
1403{ 1449{
1450 int rx_count;
1451 int over = 0;
1452
1404 SCTP_ASSERT(asoc->rwnd, "rwnd zero", return); 1453 SCTP_ASSERT(asoc->rwnd, "rwnd zero", return);
1405 SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return); 1454 SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return);
1455
1456 if (asoc->ep->rcvbuf_policy)
1457 rx_count = atomic_read(&asoc->rmem_alloc);
1458 else
1459 rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
1460
1461 /* If we've reached or overflowed our receive buffer, announce
1462 * a 0 rwnd if rwnd would still be positive. Store the
1463 * the pottential pressure overflow so that the window can be restored
1464 * back to original value.
1465 */
1466 if (rx_count >= asoc->base.sk->sk_rcvbuf)
1467 over = 1;
1468
1406 if (asoc->rwnd >= len) { 1469 if (asoc->rwnd >= len) {
1407 asoc->rwnd -= len; 1470 asoc->rwnd -= len;
1471 if (over) {
1472 asoc->rwnd_press = asoc->rwnd;
1473 asoc->rwnd = 0;
1474 }
1408 } else { 1475 } else {
1409 asoc->rwnd_over = len - asoc->rwnd; 1476 asoc->rwnd_over = len - asoc->rwnd;
1410 asoc->rwnd = 0; 1477 asoc->rwnd = 0;
1411 } 1478 }
1412 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n", 1479 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u, %u)\n",
1413 __func__, asoc, len, asoc->rwnd, 1480 __func__, asoc, len, asoc->rwnd,
1414 asoc->rwnd_over); 1481 asoc->rwnd_over, asoc->rwnd_press);
1415} 1482}
1416 1483
1417/* Build the bind address list for the association based on info from the 1484/* Build the bind address list for the association based on info from the