* Handle receipt of an acknowledgement value (Nr) from peer. */
| 1308 | * Handle receipt of an acknowledgement value (Nr) from peer. |
| 1309 | */ |
| 1310 | static void |
| 1311 | ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr) |
| 1312 | { |
| 1313 | struct l2tp_seq *const seq = &priv->seq; |
| 1314 | struct mbuf *xwin[L2TP_MAX_XWIN]; /* partial local copy */ |
| 1315 | int nack; |
| 1316 | int i, j; |
| 1317 | uint16_t ns; |
| 1318 | |
| 1319 | mtx_lock(&seq->mtx); |
| 1320 | |
| 1321 | /* Verify peer's ACK is in range */ |
| 1322 | if ((nack = L2TP_SEQ_DIFF(nr, seq->rack)) <= 0) { |
| 1323 | mtx_unlock(&seq->mtx); |
| 1324 | return; /* duplicate ack */ |
| 1325 | } |
| 1326 | if (L2TP_SEQ_DIFF(nr, seq->ns) > 0) { |
| 1327 | mtx_unlock(&seq->mtx); |
| 1328 | priv->stats.recvBadAcks++; /* ack for packet not sent */ |
| 1329 | return; |
| 1330 | } |
| 1331 | KASSERT(nack <= L2TP_MAX_XWIN, |
| 1332 | ("%s: nack=%d > %d", __func__, nack, L2TP_MAX_XWIN)); |
| 1333 | |
| 1334 | /* Update receive ack stats */ |
| 1335 | seq->rack = nr; |
| 1336 | seq->rexmits = 0; |
| 1337 | |
| 1338 | /* Free acknowledged packets and shift up packets in the xmit queue */ |
| 1339 | for (i = 0; i < nack; i++) |
| 1340 | m_freem(seq->xwin[i]); |
| 1341 | memmove(seq->xwin, seq->xwin + nack, |
| 1342 | (L2TP_MAX_XWIN - nack) * sizeof(*seq->xwin)); |
| 1343 | memset(seq->xwin + (L2TP_MAX_XWIN - nack), 0, |
| 1344 | nack * sizeof(*seq->xwin)); |
| 1345 | |
| 1346 | /* |
| 1347 | * Do slow-start/congestion avoidance windowing algorithm described |
| 1348 | * in RFC 2661, Appendix A. Here we handle a multiple ACK as if each |
| 1349 | * ACK had arrived separately. |
| 1350 | */ |
| 1351 | if (seq->cwnd < seq->wmax) { |
| 1352 | /* Handle slow start phase */ |
| 1353 | if (seq->cwnd < seq->ssth) { |
| 1354 | seq->cwnd += nack; |
| 1355 | nack = 0; |
| 1356 | if (seq->cwnd > seq->ssth) { /* into cg.av. phase */ |
| 1357 | nack = seq->cwnd - seq->ssth; |
| 1358 | seq->cwnd = seq->ssth; |
| 1359 | } |
| 1360 | } |
| 1361 | |
| 1362 | /* Handle congestion avoidance phase */ |
| 1363 | if (seq->cwnd >= seq->ssth) { |
| 1364 | seq->acks += nack; |
| 1365 | while (seq->acks >= seq->cwnd) { |
| 1366 | seq->acks -= seq->cwnd; |
| 1367 | if (seq->cwnd < seq->wmax) |
no test coverage detected