diff options
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r-- | net/sctp/associola.c | 211 |
1 files changed, 96 insertions, 115 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5ae609200674..ee13d28d39d1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1239,78 +1239,107 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | /* Update the retran path for sending a retransmitted packet. | 1241 | /* Update the retran path for sending a retransmitted packet. |
1242 | * Round-robin through the active transports, else round-robin | 1242 | * See also RFC4960, 6.4. Multi-Homed SCTP Endpoints: |
1243 | * through the inactive transports as this is the next best thing | 1243 | * |
1244 | * we can try. | 1244 | * When there is outbound data to send and the primary path |
1245 | * becomes inactive (e.g., due to failures), or where the | ||
1246 | * SCTP user explicitly requests to send data to an | ||
1247 | * inactive destination transport address, before reporting | ||
1248 | * an error to its ULP, the SCTP endpoint should try to send | ||
1249 | * the data to an alternate active destination transport | ||
1250 | * address if one exists. | ||
1251 | * | ||
1252 | * When retransmitting data that timed out, if the endpoint | ||
1253 | * is multihomed, it should consider each source-destination | ||
1254 | * address pair in its retransmission selection policy. | ||
1255 | * When retransmitting timed-out data, the endpoint should | ||
1256 | * attempt to pick the most divergent source-destination | ||
1257 | * pair from the original source-destination pair to which | ||
1258 | * the packet was transmitted. | ||
1259 | * | ||
1260 | * Note: Rules for picking the most divergent source-destination | ||
1261 | * pair are an implementation decision and are not specified | ||
1262 | * within this document. | ||
1263 | * | ||
1264 | * Our basic strategy is to round-robin transports in priorities | ||
1265 | * according to sctp_state_prio_map[] e.g., if no such | ||
1266 | * transport with state SCTP_ACTIVE exists, round-robin through | ||
1267 | * SCTP_UNKNOWN, etc. You get the picture. | ||
1245 | */ | 1268 | */ |
1246 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) | 1269 | static const u8 sctp_trans_state_to_prio_map[] = { |
1270 | [SCTP_ACTIVE] = 3, /* best case */ | ||
1271 | [SCTP_UNKNOWN] = 2, | ||
1272 | [SCTP_PF] = 1, | ||
1273 | [SCTP_INACTIVE] = 0, /* worst case */ | ||
1274 | }; | ||
1275 | |||
1276 | static u8 sctp_trans_score(const struct sctp_transport *trans) | ||
1247 | { | 1277 | { |
1248 | struct sctp_transport *t, *next; | 1278 | return sctp_trans_state_to_prio_map[trans->state]; |
1249 | struct list_head *head = &asoc->peer.transport_addr_list; | 1279 | } |
1250 | struct list_head *pos; | ||
1251 | 1280 | ||
1252 | if (asoc->peer.transport_count == 1) | 1281 | static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, |
1253 | return; | 1282 | struct sctp_transport *best) |
1283 | { | ||
1284 | if (best == NULL) | ||
1285 | return curr; | ||
1254 | 1286 | ||
1255 | /* Find the next transport in a round-robin fashion. */ | 1287 | return sctp_trans_score(curr) > sctp_trans_score(best) ? curr : best; |
1256 | t = asoc->peer.retran_path; | 1288 | } |
1257 | pos = &t->transports; | ||
1258 | next = NULL; | ||
1259 | 1289 | ||
1260 | while (1) { | 1290 | void sctp_assoc_update_retran_path(struct sctp_association *asoc) |
1261 | /* Skip the head. */ | 1291 | { |
1262 | if (pos->next == head) | 1292 | struct sctp_transport *trans = asoc->peer.retran_path; |
1263 | pos = head->next; | 1293 | struct sctp_transport *trans_next = NULL; |
1264 | else | ||
1265 | pos = pos->next; | ||
1266 | 1294 | ||
1267 | t = list_entry(pos, struct sctp_transport, transports); | 1295 | /* We're done as we only have the one and only path. */ |
1296 | if (asoc->peer.transport_count == 1) | ||
1297 | return; | ||
1298 | /* If active_path and retran_path are the same and active, | ||
1299 | * then this is the only active path. Use it. | ||
1300 | */ | ||
1301 | if (asoc->peer.active_path == asoc->peer.retran_path && | ||
1302 | asoc->peer.active_path->state == SCTP_ACTIVE) | ||
1303 | return; | ||
1268 | 1304 | ||
1269 | /* We have exhausted the list, but didn't find any | 1305 | /* Iterate from retran_path's successor back to retran_path. */ |
1270 | * other active transports. If so, use the next | 1306 | for (trans = list_next_entry(trans, transports); 1; |
1271 | * transport. | 1307 | trans = list_next_entry(trans, transports)) { |
1272 | */ | 1308 | /* Manually skip the head element. */ |
1273 | if (t == asoc->peer.retran_path) { | 1309 | if (&trans->transports == &asoc->peer.transport_addr_list) |
1274 | t = next; | 1310 | continue; |
1311 | if (trans->state == SCTP_UNCONFIRMED) | ||
1312 | continue; | ||
1313 | trans_next = sctp_trans_elect_best(trans, trans_next); | ||
1314 | /* Active is good enough for immediate return. */ | ||
1315 | if (trans_next->state == SCTP_ACTIVE) | ||
1275 | break; | 1316 | break; |
1276 | } | 1317 | /* We've reached the end, time to update path. */ |
1277 | 1318 | if (trans == asoc->peer.retran_path) | |
1278 | /* Try to find an active transport. */ | ||
1279 | |||
1280 | if ((t->state == SCTP_ACTIVE) || | ||
1281 | (t->state == SCTP_UNKNOWN)) { | ||
1282 | break; | 1319 | break; |
1283 | } else { | ||
1284 | /* Keep track of the next transport in case | ||
1285 | * we don't find any active transport. | ||
1286 | */ | ||
1287 | if (t->state != SCTP_UNCONFIRMED && !next) | ||
1288 | next = t; | ||
1289 | } | ||
1290 | } | 1320 | } |
1291 | 1321 | ||
1292 | if (t) | 1322 | if (trans_next != NULL) |
1293 | asoc->peer.retran_path = t; | 1323 | asoc->peer.retran_path = trans_next; |
1294 | else | ||
1295 | t = asoc->peer.retran_path; | ||
1296 | 1324 | ||
1297 | pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, | 1325 | pr_debug("%s: association:%p updated new path to addr:%pISpc\n", |
1298 | &t->ipaddr.sa); | 1326 | __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); |
1299 | } | 1327 | } |
1300 | 1328 | ||
1301 | /* Choose the transport for sending retransmit packet. */ | 1329 | struct sctp_transport * |
1302 | struct sctp_transport *sctp_assoc_choose_alter_transport( | 1330 | sctp_assoc_choose_alter_transport(struct sctp_association *asoc, |
1303 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) | 1331 | struct sctp_transport *last_sent_to) |
1304 | { | 1332 | { |
1305 | /* If this is the first time packet is sent, use the active path, | 1333 | /* If this is the first time packet is sent, use the active path, |
1306 | * else use the retran path. If the last packet was sent over the | 1334 | * else use the retran path. If the last packet was sent over the |
1307 | * retran path, update the retran path and use it. | 1335 | * retran path, update the retran path and use it. |
1308 | */ | 1336 | */ |
1309 | if (!last_sent_to) | 1337 | if (last_sent_to == NULL) { |
1310 | return asoc->peer.active_path; | 1338 | return asoc->peer.active_path; |
1311 | else { | 1339 | } else { |
1312 | if (last_sent_to == asoc->peer.retran_path) | 1340 | if (last_sent_to == asoc->peer.retran_path) |
1313 | sctp_assoc_update_retran_path(asoc); | 1341 | sctp_assoc_update_retran_path(asoc); |
1342 | |||
1314 | return asoc->peer.retran_path; | 1343 | return asoc->peer.retran_path; |
1315 | } | 1344 | } |
1316 | } | 1345 | } |
@@ -1367,44 +1396,35 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) | |||
1367 | return false; | 1396 | return false; |
1368 | } | 1397 | } |
1369 | 1398 | ||
1370 | /* Increase asoc's rwnd by len and send any window update SACK if needed. */ | 1399 | /* Update asoc's rwnd for the approximated state in the buffer, |
1371 | void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) | 1400 | * and check whether SACK needs to be sent. |
1401 | */ | ||
1402 | void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | ||
1372 | { | 1403 | { |
1404 | int rx_count; | ||
1373 | struct sctp_chunk *sack; | 1405 | struct sctp_chunk *sack; |
1374 | struct timer_list *timer; | 1406 | struct timer_list *timer; |
1375 | 1407 | ||
1376 | if (asoc->rwnd_over) { | 1408 | if (asoc->ep->rcvbuf_policy) |
1377 | if (asoc->rwnd_over >= len) { | 1409 | rx_count = atomic_read(&asoc->rmem_alloc); |
1378 | asoc->rwnd_over -= len; | 1410 | else |
1379 | } else { | 1411 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); |
1380 | asoc->rwnd += (len - asoc->rwnd_over); | ||
1381 | asoc->rwnd_over = 0; | ||
1382 | } | ||
1383 | } else { | ||
1384 | asoc->rwnd += len; | ||
1385 | } | ||
1386 | 1412 | ||
1387 | /* If we had window pressure, start recovering it | 1413 | if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) |
1388 | * once our rwnd had reached the accumulated pressure | 1414 | asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; |
1389 | * threshold. The idea is to recover slowly, but up | 1415 | else |
1390 | * to the initial advertised window. | 1416 | asoc->rwnd = 0; |
1391 | */ | ||
1392 | if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { | ||
1393 | int change = min(asoc->pathmtu, asoc->rwnd_press); | ||
1394 | asoc->rwnd += change; | ||
1395 | asoc->rwnd_press -= change; | ||
1396 | } | ||
1397 | 1417 | ||
1398 | pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", | 1418 | pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", |
1399 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | 1419 | __func__, asoc, asoc->rwnd, rx_count, |
1400 | asoc->a_rwnd); | 1420 | asoc->base.sk->sk_rcvbuf); |
1401 | 1421 | ||
1402 | /* Send a window update SACK if the rwnd has increased by at least the | 1422 | /* Send a window update SACK if the rwnd has increased by at least the |
1403 | * minimum of the association's PMTU and half of the receive buffer. | 1423 | * minimum of the association's PMTU and half of the receive buffer. |
1404 | * The algorithm used is similar to the one described in | 1424 | * The algorithm used is similar to the one described in |
1405 | * Section 4.2.3.3 of RFC 1122. | 1425 | * Section 4.2.3.3 of RFC 1122. |
1406 | */ | 1426 | */ |
1407 | if (sctp_peer_needs_update(asoc)) { | 1427 | if (update_peer && sctp_peer_needs_update(asoc)) { |
1408 | asoc->a_rwnd = asoc->rwnd; | 1428 | asoc->a_rwnd = asoc->rwnd; |
1409 | 1429 | ||
1410 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " | 1430 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " |
@@ -1426,45 +1446,6 @@ void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) | |||
1426 | } | 1446 | } |
1427 | } | 1447 | } |
1428 | 1448 | ||
1429 | /* Decrease asoc's rwnd by len. */ | ||
1430 | void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) | ||
1431 | { | ||
1432 | int rx_count; | ||
1433 | int over = 0; | ||
1434 | |||
1435 | if (unlikely(!asoc->rwnd || asoc->rwnd_over)) | ||
1436 | pr_debug("%s: association:%p has asoc->rwnd:%u, " | ||
1437 | "asoc->rwnd_over:%u!\n", __func__, asoc, | ||
1438 | asoc->rwnd, asoc->rwnd_over); | ||
1439 | |||
1440 | if (asoc->ep->rcvbuf_policy) | ||
1441 | rx_count = atomic_read(&asoc->rmem_alloc); | ||
1442 | else | ||
1443 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | ||
1444 | |||
1445 | /* If we've reached or overflowed our receive buffer, announce | ||
1446 | * a 0 rwnd if rwnd would still be positive. Store the | ||
1447 | * the potential pressure overflow so that the window can be restored | ||
1448 | * back to original value. | ||
1449 | */ | ||
1450 | if (rx_count >= asoc->base.sk->sk_rcvbuf) | ||
1451 | over = 1; | ||
1452 | |||
1453 | if (asoc->rwnd >= len) { | ||
1454 | asoc->rwnd -= len; | ||
1455 | if (over) { | ||
1456 | asoc->rwnd_press += asoc->rwnd; | ||
1457 | asoc->rwnd = 0; | ||
1458 | } | ||
1459 | } else { | ||
1460 | asoc->rwnd_over = len - asoc->rwnd; | ||
1461 | asoc->rwnd = 0; | ||
1462 | } | ||
1463 | |||
1464 | pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", | ||
1465 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | ||
1466 | asoc->rwnd_press); | ||
1467 | } | ||
1468 | 1449 | ||
1469 | /* Build the bind address list for the association based on info from the | 1450 | /* Build the bind address list for the association based on info from the |
1470 | * local endpoint and the remote peer. | 1451 | * local endpoint and the remote peer. |