@@ -1396,35 +1396,44 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc)
1396
1396
return false;
1397
1397
}
1398
1398
1399
- /* Update asoc's rwnd for the approximated state in the buffer,
1400
- * and check whether SACK needs to be sent.
1401
- */
1402
- void sctp_assoc_rwnd_update (struct sctp_association * asoc , bool update_peer )
1399
+ /* Increase asoc's rwnd by len and send any window update SACK if needed. */
1400
+ void sctp_assoc_rwnd_increase (struct sctp_association * asoc , unsigned int len )
1403
1401
{
1404
- int rx_count ;
1405
1402
struct sctp_chunk * sack ;
1406
1403
struct timer_list * timer ;
1407
1404
1408
- if (asoc -> ep -> rcvbuf_policy )
1409
- rx_count = atomic_read (& asoc -> rmem_alloc );
1410
- else
1411
- rx_count = atomic_read (& asoc -> base .sk -> sk_rmem_alloc );
1405
+ if (asoc -> rwnd_over ) {
1406
+ if (asoc -> rwnd_over >= len ) {
1407
+ asoc -> rwnd_over -= len ;
1408
+ } else {
1409
+ asoc -> rwnd += (len - asoc -> rwnd_over );
1410
+ asoc -> rwnd_over = 0 ;
1411
+ }
1412
+ } else {
1413
+ asoc -> rwnd += len ;
1414
+ }
1412
1415
1413
- if ((asoc -> base .sk -> sk_rcvbuf - rx_count ) > 0 )
1414
- asoc -> rwnd = (asoc -> base .sk -> sk_rcvbuf - rx_count ) >> 1 ;
1415
- else
1416
- asoc -> rwnd = 0 ;
1416
+ /* If we had window pressure, start recovering it
1417
+ * once our rwnd had reached the accumulated pressure
1418
+ * threshold. The idea is to recover slowly, but up
1419
+ * to the initial advertised window.
1420
+ */
1421
+ if (asoc -> rwnd_press && asoc -> rwnd >= asoc -> rwnd_press ) {
1422
+ int change = min (asoc -> pathmtu , asoc -> rwnd_press );
1423
+ asoc -> rwnd += change ;
1424
+ asoc -> rwnd_press -= change ;
1425
+ }
1417
1426
1418
- pr_debug ("%s: asoc:%p rwnd=% u, rx_count=%d, sk_rcvbuf=%d \n" ,
1419
- __func__ , asoc , asoc -> rwnd , rx_count ,
1420
- asoc -> base . sk -> sk_rcvbuf );
1427
+ pr_debug ("%s: asoc:%p rwnd increased by %d to (% u, %u) - %u \n" ,
1428
+ __func__ , asoc , len , asoc -> rwnd , asoc -> rwnd_over ,
1429
+ asoc -> a_rwnd );
1421
1430
1422
1431
/* Send a window update SACK if the rwnd has increased by at least the
1423
1432
* minimum of the association's PMTU and half of the receive buffer.
1424
1433
* The algorithm used is similar to the one described in
1425
1434
* Section 4.2.3.3 of RFC 1122.
1426
1435
*/
1427
- if (update_peer && sctp_peer_needs_update (asoc )) {
1436
+ if (sctp_peer_needs_update (asoc )) {
1428
1437
asoc -> a_rwnd = asoc -> rwnd ;
1429
1438
1430
1439
pr_debug ("%s: sending window update SACK- asoc:%p rwnd:%u "
@@ -1446,6 +1455,45 @@ void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer)
1446
1455
}
1447
1456
}
1448
1457
1458
+ /* Decrease asoc's rwnd by len. */
1459
+ void sctp_assoc_rwnd_decrease (struct sctp_association * asoc , unsigned int len )
1460
+ {
1461
+ int rx_count ;
1462
+ int over = 0 ;
1463
+
1464
+ if (unlikely (!asoc -> rwnd || asoc -> rwnd_over ))
1465
+ pr_debug ("%s: association:%p has asoc->rwnd:%u, "
1466
+ "asoc->rwnd_over:%u!\n" , __func__ , asoc ,
1467
+ asoc -> rwnd , asoc -> rwnd_over );
1468
+
1469
+ if (asoc -> ep -> rcvbuf_policy )
1470
+ rx_count = atomic_read (& asoc -> rmem_alloc );
1471
+ else
1472
+ rx_count = atomic_read (& asoc -> base .sk -> sk_rmem_alloc );
1473
+
1474
+ /* If we've reached or overflowed our receive buffer, announce
1475
+ * a 0 rwnd if rwnd would still be positive. Store the
1476
+ * the potential pressure overflow so that the window can be restored
1477
+ * back to original value.
1478
+ */
1479
+ if (rx_count >= asoc -> base .sk -> sk_rcvbuf )
1480
+ over = 1 ;
1481
+
1482
+ if (asoc -> rwnd >= len ) {
1483
+ asoc -> rwnd -= len ;
1484
+ if (over ) {
1485
+ asoc -> rwnd_press += asoc -> rwnd ;
1486
+ asoc -> rwnd = 0 ;
1487
+ }
1488
+ } else {
1489
+ asoc -> rwnd_over = len - asoc -> rwnd ;
1490
+ asoc -> rwnd = 0 ;
1491
+ }
1492
+
1493
+ pr_debug ("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n" ,
1494
+ __func__ , asoc , len , asoc -> rwnd , asoc -> rwnd_over ,
1495
+ asoc -> rwnd_press );
1496
+ }
1449
1497
1450
1498
/* Build the bind address list for the association based on info from the
1451
1499
* local endpoint and the remote peer.
0 commit comments