Merge branch 'sctp-pmtu-probe'

Xin Long says:

====================
sctp: improve the pmtu probe in Search Complete state

Timo recently suggested to use the loss of (data) packets as
indication to send pmtu probe for Search Complete state, which
should also be implied by RFC8899. This patchset is to change
the current one that is doing probe with current pmtu all the
time.

v1->v2:
  - see Patch 2/2.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-07-25 23:06:21 +01:00
commit 832df96d5f
3 changed files with 37 additions and 28 deletions

View File

@ -984,6 +984,7 @@ struct sctp_transport {
} cacc;
struct {
__u32 last_rtx_chunks;
__u16 pmtu;
__u16 probe_size;
__u16 probe_high;
@ -1024,8 +1025,8 @@ bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu);
void sctp_transport_immediate_rtx(struct sctp_transport *);
void sctp_transport_dst_release(struct sctp_transport *t);
void sctp_transport_dst_confirm(struct sctp_transport *t);
void sctp_transport_pl_send(struct sctp_transport *t);
void sctp_transport_pl_recv(struct sctp_transport *t);
bool sctp_transport_pl_send(struct sctp_transport *t);
bool sctp_transport_pl_recv(struct sctp_transport *t);
/* This is the structure we use to queue packets as they come into

View File

@ -1109,12 +1109,12 @@ enum sctp_disposition sctp_sf_send_probe(struct net *net,
if (!sctp_transport_pl_enabled(transport))
return SCTP_DISPOSITION_CONSUME;
sctp_transport_pl_send(transport);
reply = sctp_make_heartbeat(asoc, transport, transport->pl.probe_size);
if (!reply)
return SCTP_DISPOSITION_NOMEM;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
if (sctp_transport_pl_send(transport)) {
reply = sctp_make_heartbeat(asoc, transport, transport->pl.probe_size);
if (!reply)
return SCTP_DISPOSITION_NOMEM;
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));
}
sctp_add_cmd_sf(commands, SCTP_CMD_PROBE_TIMER_UPDATE,
SCTP_TRANSPORT(transport));
@ -1274,8 +1274,7 @@ enum sctp_disposition sctp_sf_backbeat_8_3(struct net *net,
!sctp_transport_pl_enabled(link))
return SCTP_DISPOSITION_DISCARD;
sctp_transport_pl_recv(link);
if (link->pl.state == SCTP_PL_COMPLETE)
if (sctp_transport_pl_recv(link))
return SCTP_DISPOSITION_CONSUME;
return sctp_sf_send_probe(net, ep, asoc, type, link, commands);

View File

@ -258,16 +258,13 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
sctp_transport_pl_update(transport);
}
void sctp_transport_pl_send(struct sctp_transport *t)
bool sctp_transport_pl_send(struct sctp_transport *t)
{
pr_debug("%s: PLPMTUD: transport: %p, state: %d, pmtu: %d, size: %d, high: %d\n",
__func__, t, t->pl.state, t->pl.pmtu, t->pl.probe_size, t->pl.probe_high);
if (t->pl.probe_count < SCTP_MAX_PROBES) {
t->pl.probe_count++;
return;
}
if (t->pl.probe_count < SCTP_MAX_PROBES)
goto out;
t->pl.last_rtx_chunks = t->asoc->rtx_data_chunks;
t->pl.probe_count = 0;
if (t->pl.state == SCTP_PL_BASE) {
if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */
t->pl.state = SCTP_PL_ERROR; /* Base -> Error */
@ -299,14 +296,27 @@ void sctp_transport_pl_send(struct sctp_transport *t)
sctp_assoc_sync_pmtu(t->asoc);
}
}
t->pl.probe_count = 1;
out:
if (t->pl.state == SCTP_PL_COMPLETE && t->pl.raise_count < 30 &&
!t->pl.probe_count && t->pl.last_rtx_chunks == t->asoc->rtx_data_chunks) {
t->pl.raise_count++;
return false;
}
pr_debug("%s: PLPMTUD: transport: %p, state: %d, pmtu: %d, size: %d, high: %d\n",
__func__, t, t->pl.state, t->pl.pmtu, t->pl.probe_size, t->pl.probe_high);
t->pl.probe_count++;
return true;
}
void sctp_transport_pl_recv(struct sctp_transport *t)
bool sctp_transport_pl_recv(struct sctp_transport *t)
{
pr_debug("%s: PLPMTUD: transport: %p, state: %d, pmtu: %d, size: %d, high: %d\n",
__func__, t, t->pl.state, t->pl.pmtu, t->pl.probe_size, t->pl.probe_high);
t->pl.last_rtx_chunks = t->asoc->rtx_data_chunks;
t->pl.pmtu = t->pl.probe_size;
t->pl.probe_count = 0;
if (t->pl.state == SCTP_PL_BASE) {
@ -323,7 +333,7 @@ void sctp_transport_pl_recv(struct sctp_transport *t)
if (!t->pl.probe_high) {
t->pl.probe_size = min(t->pl.probe_size + SCTP_PL_BIG_STEP,
SCTP_MAX_PLPMTU);
return;
return false;
}
t->pl.probe_size += SCTP_PL_MIN_STEP;
if (t->pl.probe_size >= t->pl.probe_high) {
@ -335,14 +345,13 @@ void sctp_transport_pl_recv(struct sctp_transport *t)
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
sctp_assoc_sync_pmtu(t->asoc);
}
} else if (t->pl.state == SCTP_PL_COMPLETE) {
t->pl.raise_count++;
if (t->pl.raise_count == 30) {
/* Raise probe_size again after 30 * interval in Search Complete */
t->pl.state = SCTP_PL_SEARCH; /* Search Complete -> Search */
t->pl.probe_size += SCTP_PL_MIN_STEP;
}
} else if (t->pl.state == SCTP_PL_COMPLETE && t->pl.raise_count == 30) {
/* Raise probe_size again after 30 * interval in Search Complete */
t->pl.state = SCTP_PL_SEARCH; /* Search Complete -> Search */
t->pl.probe_size += SCTP_PL_MIN_STEP;
}
return t->pl.state == SCTP_PL_COMPLETE;
}
static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu)