Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEV9: Improve speed of TCP connections on the sockets backend #11046

Merged
merged 5 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions pcsx2/DEV9/Sessions/TCP_Session/TCP_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,27 @@ namespace Sessions

_MySequenceNumber += amount;
}
void TCP_Session::UpdateReceivedAckNumber(u32 ack)
{
std::lock_guard numberlock(myNumberSentry);
if (GetDelta(ack, _ReceivedAckNumber) > 0)
_ReceivedAckNumber = ack;
}
u32 TCP_Session::GetMyNumber()
{
std::lock_guard numberlock(myNumberSentry);
return _MySequenceNumber;
}
u32 TCP_Session::GetOutstandingSequenceLength()
{
std::lock_guard numberlock(myNumberSentry);
return GetDelta(_MySequenceNumber, _ReceivedAckNumber);
}
bool TCP_Session::ShouldWaitForAck()
{
std::lock_guard numberlock(myNumberSentry);
return _OldMyNumbers[0] == _ReceivedAckNumber;
}
std::tuple<u32, std::vector<u32>> TCP_Session::GetAllMyNumbers()
{
std::lock_guard numberlock(myNumberSentry);
Expand All @@ -68,6 +84,24 @@ namespace Sessions
{
}

s32 TCP_Session::GetDelta(u32 a, u32 b)
{
s64 delta = static_cast<s64>(a) - static_cast<s64>(b);
if (delta > 0.5 * UINT_MAX)
{
delta = -static_cast<s64>(UINT_MAX) + a - b - 1;
Console.Error("DEV9: TCP: [PS2] SequenceNumber Overflow Detected");
Console.Error("DEV9: TCP: [PS2] New Data Offset: %d bytes", delta);
}
if (delta < -0.5 * UINT_MAX)
{
delta = UINT_MAX - b + a + 1;
Console.Error("DEV9: TCP: [PS2] SequenceNumber Overflow Detected");
Console.Error("DEV9: TCP: [PS2] New Data Offset: %d bytes", delta);
}
return delta;
}

TCP_Packet* TCP_Session::CreateBasePacket(PayloadData* data)
{
//DevCon.WriteLn("Creating Base Packet");
Expand All @@ -81,9 +115,9 @@ namespace Sessions
ret->destinationPort = srcPort;

ret->sequenceNumber = GetMyNumber();
//DevCon.WriteLn("With MySeq: %d", ret->sequenceNumber);
//DevCon.WriteLn("With MySeq: %u", ret->sequenceNumber);
ret->acknowledgementNumber = expectedSeqNumber;
//DevCon.WriteLn("With MyAck: %d", ret->acknowledgementNumber);
//DevCon.WriteLn("With MyAck: %u", ret->acknowledgementNumber);

ret->windowSize = 2 * maxSegmentSize;

Expand Down
8 changes: 6 additions & 2 deletions pcsx2/DEV9/Sessions/TCP_Session/TCP_Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ namespace Sessions
std::vector<u32> receivedPS2SeqNumbers; //Accesed By Out Thread Only

std::mutex myNumberSentry;
const int oldMyNumCount = 2;
const int oldMyNumCount = 64;
u32 _MySequenceNumber = 1;
std::vector<u32> _OldMyNumbers;
u32 _ReceivedAckNumber = 1;
std::atomic<bool> myNumberACKed{true};

public:
Expand All @@ -89,13 +90,16 @@ namespace Sessions
PacketReader::IP::TCP::TCP_Packet* PopRecvBuff();

void IncrementMyNumber(u32 amount);
void UpdateReceivedAckNumber(u32 ack);
u32 GetMyNumber();
u32 GetOutstandingSequenceLength();
bool ShouldWaitForAck();
std::tuple<u32, std::vector<u32>> GetAllMyNumbers();
void ResetMyNumbers();

NumCheckResult CheckRepeatSYNNumbers(PacketReader::IP::TCP::TCP_Packet* tcp);
NumCheckResult CheckNumbers(PacketReader::IP::TCP::TCP_Packet* tcp);
u32 GetDelta(u32 parExpectedSeq, u32 parGotSeq);
s32 GetDelta(u32 a, u32 b); //Returns a - b
//Returns true if errored
bool ErrorOnNonEmptyPacket(PacketReader::IP::TCP::TCP_Packet* tcp);

Expand Down
24 changes: 16 additions & 8 deletions pcsx2/DEV9/Sessions/TCP_Session/TCP_Session_In.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,37 @@ namespace Sessions
return nullptr;
}

uint maxSize = 0;
if (ShouldWaitForAck())
return nullptr;

//Note, windowSize will be updated before _ReceivedAckNumber, potential race condition
//in practice, we just get a smaller or -ve maxSize
const u32 outstanding = GetOutstandingSequenceLength();

int maxSize = 0;
if (sendTimeStamps)
maxSize = std::min<uint>(maxSegmentSize - 12, windowSize.load());
maxSize = std::min<int>(maxSegmentSize - 12, windowSize.load() - outstanding);
else
maxSize = std::min<uint>(maxSegmentSize, windowSize.load());
maxSize = std::min<int>(maxSegmentSize, windowSize.load() - outstanding);

if (maxSize != 0 &&
myNumberACKed.load())
if (maxSize > 0)
{
std::unique_ptr<u8[]> buffer;
int err = 0;
int recived;

unsigned long available;
//FIONREAD uses unsigned long on windows and int on linux
//Zero init so we don't have bad data on any unused bytes
unsigned long available = 0;
#ifdef _WIN32
err = ioctlsocket(client, FIONREAD, &available);
#elif defined(__POSIX__)
err = ioctl(client, FIONREAD, &available);
#endif
if (err != SOCKET_ERROR)
{
if (available > maxSize)
Console.WriteLn("DEV9: TCP: Got a lot of data: %d Using: %d", available, maxSize);
if (available > static_cast<uint>(maxSize))
Console.WriteLn("DEV9: TCP: Got a lot of data: %lu Using: %d", available, maxSize);

buffer = std::make_unique<u8[]>(maxSize);
recived = recv(client, (char*)buffer.get(), maxSize, 0);
Expand Down
39 changes: 16 additions & 23 deletions pcsx2/DEV9/Sessions/TCP_Session/TCP_Session_Out.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,9 @@ namespace Sessions
windowSize.store(tcp->windowSize << windowScale);

const NumCheckResult Result = CheckNumbers(tcp);
//Check if we already have some of the data sent
const uint delta = GetDelta(expectedSeqNumber, tcp->sequenceNumber);
pxAssert(delta >= 0);
//if (Result == NumCheckResult::GotOldData)
//{
// DevCon.WriteLn("[PS2] New Data Offset: %d bytes", delta);
Expand Down Expand Up @@ -361,7 +363,7 @@ namespace Sessions
//Done send
}
//ACK data
//DevCon.WriteLn("[SRV] ACK Data: %d", expectedSeqNumber);
//DevCon.WriteLn("[SRV] ACK Data: %u", expectedSeqNumber);
TCP_Packet* ret = CreateBasePacket();
ret->SetACK(true);

Expand Down Expand Up @@ -402,11 +404,11 @@ namespace Sessions
TCP_Session::NumCheckResult TCP_Session::CheckRepeatSYNNumbers(TCP_Packet* tcp)
{
//DevCon.WriteLn("DEV9: TCP: CHECK_REPEAT_SYN_NUMBERS");
//DevCon.WriteLn("DEV9: TCP: [SRV]CurrAckNumber = %d [PS2]Seq Number = %d", expectedSeqNumber, tcp->sequenceNumber);
//DevCon.WriteLn("DEV9: TCP: [SRV] CurrAckNumber = %u [PS2] Seq Number = %u", expectedSeqNumber, tcp->sequenceNumber);

if (tcp->sequenceNumber != expectedSeqNumber - 1)
{
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From Repeated SYN Packet, Got %d Expected %d", tcp->sequenceNumber, (expectedSeqNumber - 1));
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From Repeated SYN Packet, Got %u Expected %u", tcp->sequenceNumber, (expectedSeqNumber - 1));
return NumCheckResult::Bad;
}
return NumCheckResult::OK;
Expand All @@ -419,62 +421,53 @@ namespace Sessions
std::tie(seqNum, oldSeqNums) = GetAllMyNumbers();

//DevCon.WriteLn("DEV9: TCP: CHECK_NUMBERS");
//DevCon.WriteLn("DEV9: TCP: [SRV]CurrSeqNumber = %d [PS2]Ack Number = %d", seqNum, tcp->acknowledgementNumber);
//DevCon.WriteLn("DEV9: TCP: [SRV]CurrAckNumber = %d [PS2]Seq Number = %d", expectedSeqNumber, tcp->sequenceNumber);
//DevCon.WriteLn("DEV9: TCP: [PS2]Data Length = %d", tcp->GetPayload()->GetLength());
//DevCon.WriteLn("DEV9: TCP: [SRV] CurrSeqNumber = %u [PS2] Ack Number = %u", seqNum, tcp->acknowledgementNumber);
//DevCon.WriteLn("DEV9: TCP: [SRV] CurrAckNumber = %u [PS2] Seq Number = %u", expectedSeqNumber, tcp->sequenceNumber);
//DevCon.WriteLn("DEV9: TCP: [PS2] Data Length = %u", tcp->GetPayload()->GetLength());

if (tcp->acknowledgementNumber != seqNum)
{
//DevCon.WriteLn("DEV9: TCP: [PS2]Sent Outdated Acknowledgement Number, Got %d Expected %d", tcp->acknowledgementNumber, seqNum);
//DevCon.WriteLn("DEV9: TCP: [PS2] Sent Outdated Acknowledgement Number, Got %u Expected %u", tcp->acknowledgementNumber, seqNum);

//Check if oldSeqNums contains tcp->acknowledgementNumber
if (std::find(oldSeqNums.begin(), oldSeqNums.end(), tcp->acknowledgementNumber) == oldSeqNums.end())
{
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Acknowledgement Number, did not Match Old Numbers, Got %d Expected %d", tcp->acknowledgementNumber, seqNum);
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Acknowledgement Number, did not Match Old Numbers, Got %u Expected %u", tcp->acknowledgementNumber, seqNum);
return NumCheckResult::Bad;
}
}
else
{
//DevCon.WriteLn("[PS2]CurrSeqNumber Acknowleged By PS2");
//DevCon.WriteLn("[PS2] CurrSeqNumber Acknowleged By PS2");
myNumberACKed.store(true);
}

UpdateReceivedAckNumber(tcp->acknowledgementNumber);

if (tcp->sequenceNumber != expectedSeqNumber)
{
if (tcp->GetPayload()->GetLength() == 0)
{
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From ACK Packet, Got %d Expected %d", tcp->sequenceNumber, expectedSeqNumber);
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From ACK Packet, Got %u Expected %u", tcp->sequenceNumber, expectedSeqNumber);
}
else
{
//Check if receivedPS2SeqNumbers contains tcp->sequenceNumber
if (std::find(receivedPS2SeqNumbers.begin(), receivedPS2SeqNumbers.end(), tcp->sequenceNumber) == receivedPS2SeqNumbers.end())
{
Console.Error("DEV9: TCP: [PS2] Sent an Old Seq Number on an Data packet, Got %d Expected %d", tcp->sequenceNumber, expectedSeqNumber);
Console.Error("DEV9: TCP: [PS2] Sent an Old Seq Number on an Data packet, Got %u Expected %u", tcp->sequenceNumber, expectedSeqNumber);
return NumCheckResult::GotOldData;
}
else
{
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From Data Packet, Got %d Expected %d", tcp->sequenceNumber, expectedSeqNumber);
Console.Error("DEV9: TCP: [PS2] Sent Unexpected Sequence Number From Data Packet, Got %u Expected %u", tcp->sequenceNumber, expectedSeqNumber);
return NumCheckResult::Bad;
}
}
}

return NumCheckResult::OK;
}
u32 TCP_Session::GetDelta(u32 parExpectedSeq, u32 parGotSeq)
{
u32 delta = parExpectedSeq - parGotSeq;
if (delta > 0.5 * UINT_MAX)
{
delta = UINT_MAX - parExpectedSeq + parGotSeq;
Console.Error("DEV9: TCP: [PS2] SequenceNumber Overflow Detected");
Console.Error("DEV9: TCP: [PS2] New Data Offset: %d bytes", delta);
}
return delta;
}
bool TCP_Session::ErrorOnNonEmptyPacket(TCP_Packet* tcp)
{
NumCheckResult ResultFIN = CheckNumbers(tcp);
Expand Down