aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sctp/associola.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 215b56951d76..39c3821b7d3d 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -202,6 +202,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
202 asoc->a_rwnd = asoc->rwnd; 202 asoc->a_rwnd = asoc->rwnd;
203 203
204 asoc->rwnd_over = 0; 204 asoc->rwnd_over = 0;
205 asoc->rwnd_press = 0;
205 206
206 /* Use my own max window until I learn something better. */ 207 /* Use my own max window until I learn something better. */
207 asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW; 208 asoc->peer.rwnd = SCTP_DEFAULT_MAXWINDOW;
@@ -1374,6 +1375,17 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
1374 asoc->rwnd += len; 1375 asoc->rwnd += len;
1375 } 1376 }
1376 1377
1378 /* If we had window pressure, start recovering it
1379 * once our rwnd had reached the accumulated pressure
1380 * threshold. The idea is to recover slowly, but up
1381 * to the initial advertised window.
1382 */
1383 if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) {
1384 int change = min(asoc->pathmtu, asoc->rwnd_press);
1385 asoc->rwnd += change;
1386 asoc->rwnd_press -= change;
1387 }
1388
1377 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) " 1389 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd increased by %d to (%u, %u) "
1378 "- %u\n", __func__, asoc, len, asoc->rwnd, 1390 "- %u\n", __func__, asoc, len, asoc->rwnd,
1379 asoc->rwnd_over, asoc->a_rwnd); 1391 asoc->rwnd_over, asoc->a_rwnd);
@@ -1406,17 +1418,38 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned len)
1406/* Decrease asoc's rwnd by len. */ 1418/* Decrease asoc's rwnd by len. */
1407void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len) 1419void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
1408{ 1420{
1421 int rx_count;
1422 int over = 0;
1423
1409 SCTP_ASSERT(asoc->rwnd, "rwnd zero", return); 1424 SCTP_ASSERT(asoc->rwnd, "rwnd zero", return);
1410 SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return); 1425 SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return);
1426
1427 if (asoc->ep->rcvbuf_policy)
1428 rx_count = atomic_read(&asoc->rmem_alloc);
1429 else
1430 rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
1431
1432 /* If we've reached or overflowed our receive buffer, announce
1433 * a 0 rwnd if rwnd would still be positive. Store the
1434 * the pottential pressure overflow so that the window can be restored
1435 * back to original value.
1436 */
1437 if (rx_count >= asoc->base.sk->sk_rcvbuf)
1438 over = 1;
1439
1411 if (asoc->rwnd >= len) { 1440 if (asoc->rwnd >= len) {
1412 asoc->rwnd -= len; 1441 asoc->rwnd -= len;
1442 if (over) {
1443 asoc->rwnd_press = asoc->rwnd;
1444 asoc->rwnd = 0;
1445 }
1413 } else { 1446 } else {
1414 asoc->rwnd_over = len - asoc->rwnd; 1447 asoc->rwnd_over = len - asoc->rwnd;
1415 asoc->rwnd = 0; 1448 asoc->rwnd = 0;
1416 } 1449 }
1417 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n", 1450 SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u, %u)\n",
1418 __func__, asoc, len, asoc->rwnd, 1451 __func__, asoc, len, asoc->rwnd,
1419 asoc->rwnd_over); 1452 asoc->rwnd_over, asoc->rwnd_press);
1420} 1453}
1421 1454
1422/* Build the bind address list for the association based on info from the 1455/* Build the bind address list for the association based on info from the