mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-24 10:39:52 +00:00
mptcp: update per unacked sequence on pkt reception
So that we keep per unacked sequence number consistent; since we update per msk data, use an atomic64 cmpxchg() to protect against concurrent updates from multiple subflows. Initialize the snd_una at connect()/accept() time. Co-developed-by: Florian Westphal <fw@strlen.de> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
926bdeab55
commit
cc9d256698
3 changed files with 49 additions and 6 deletions
|
@ -744,6 +744,46 @@ fully_established:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 expand_ack(u64 old_ack, u64 cur_ack, bool use_64bit)
|
||||||
|
{
|
||||||
|
u32 old_ack32, cur_ack32;
|
||||||
|
|
||||||
|
if (use_64bit)
|
||||||
|
return cur_ack;
|
||||||
|
|
||||||
|
old_ack32 = (u32)old_ack;
|
||||||
|
cur_ack32 = (u32)cur_ack;
|
||||||
|
cur_ack = (old_ack & GENMASK_ULL(63, 32)) + cur_ack32;
|
||||||
|
if (unlikely(before(cur_ack32, old_ack32)))
|
||||||
|
return cur_ack + (1LL << 32);
|
||||||
|
return cur_ack;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_una(struct mptcp_sock *msk,
|
||||||
|
struct mptcp_options_received *mp_opt)
|
||||||
|
{
|
||||||
|
u64 new_snd_una, snd_una, old_snd_una = atomic64_read(&msk->snd_una);
|
||||||
|
u64 write_seq = READ_ONCE(msk->write_seq);
|
||||||
|
|
||||||
|
/* avoid ack expansion on update conflict, to reduce the risk of
|
||||||
|
* wrongly expanding to a future ack sequence number, which is way
|
||||||
|
* more dangerous than missing an ack
|
||||||
|
*/
|
||||||
|
new_snd_una = expand_ack(old_snd_una, mp_opt->data_ack, mp_opt->ack64);
|
||||||
|
|
||||||
|
/* ACK for data not even sent yet? Ignore. */
|
||||||
|
if (after64(new_snd_una, write_seq))
|
||||||
|
new_snd_una = old_snd_una;
|
||||||
|
|
||||||
|
while (after64(new_snd_una, old_snd_una)) {
|
||||||
|
snd_una = old_snd_una;
|
||||||
|
old_snd_una = atomic64_cmpxchg(&msk->snd_una, snd_una,
|
||||||
|
new_snd_una);
|
||||||
|
if (old_snd_una == snd_una)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool add_addr_hmac_valid(struct mptcp_sock *msk,
|
static bool add_addr_hmac_valid(struct mptcp_sock *msk,
|
||||||
struct mptcp_options_received *mp_opt)
|
struct mptcp_options_received *mp_opt)
|
||||||
{
|
{
|
||||||
|
@ -805,6 +845,12 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
|
||||||
if (!mp_opt->dss)
|
if (!mp_opt->dss)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* we can't wait for recvmsg() to update the ack_seq, otherwise
|
||||||
|
* monodirectional flows will stuck
|
||||||
|
*/
|
||||||
|
if (mp_opt->use_ack)
|
||||||
|
update_una(msk, mp_opt);
|
||||||
|
|
||||||
mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
|
mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
|
||||||
if (!mpext)
|
if (!mpext)
|
||||||
return;
|
return;
|
||||||
|
@ -831,12 +877,6 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
|
||||||
mpext->use_map = 1;
|
mpext->use_map = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mp_opt->use_ack) {
|
|
||||||
mpext->data_ack = mp_opt->data_ack;
|
|
||||||
mpext->use_ack = 1;
|
|
||||||
mpext->ack64 = mp_opt->ack64;
|
|
||||||
}
|
|
||||||
|
|
||||||
mpext->data_fin = mp_opt->data_fin;
|
mpext->data_fin = mp_opt->data_fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -906,6 +906,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk, struct request_sock *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
msk->write_seq = subflow_req->idsn + 1;
|
msk->write_seq = subflow_req->idsn + 1;
|
||||||
|
atomic64_set(&msk->snd_una, msk->write_seq);
|
||||||
if (subflow_req->remote_key_valid) {
|
if (subflow_req->remote_key_valid) {
|
||||||
msk->can_ack = true;
|
msk->can_ack = true;
|
||||||
msk->remote_key = subflow_req->remote_key;
|
msk->remote_key = subflow_req->remote_key;
|
||||||
|
@ -1107,6 +1108,7 @@ void mptcp_finish_connect(struct sock *ssk)
|
||||||
WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
|
WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
|
||||||
WRITE_ONCE(msk->ack_seq, ack_seq);
|
WRITE_ONCE(msk->ack_seq, ack_seq);
|
||||||
WRITE_ONCE(msk->can_ack, 1);
|
WRITE_ONCE(msk->can_ack, 1);
|
||||||
|
atomic64_set(&msk->snd_una, msk->write_seq);
|
||||||
|
|
||||||
mptcp_pm_new_connection(msk, 0);
|
mptcp_pm_new_connection(msk, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,7 @@ struct mptcp_sock {
|
||||||
u64 remote_key;
|
u64 remote_key;
|
||||||
u64 write_seq;
|
u64 write_seq;
|
||||||
u64 ack_seq;
|
u64 ack_seq;
|
||||||
|
atomic64_t snd_una;
|
||||||
u32 token;
|
u32 token;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool can_ack;
|
bool can_ack;
|
||||||
|
|
Loading…
Add table
Reference in a new issue