Debug TCP socket state listing.

This commit is contained in:
Jonas 'Sortie' Termansen 2022-06-01 11:08:06 +02:00
parent bd7e8f93f9
commit 1e82d88906
3 changed files with 116 additions and 3 deletions

View File

@ -24,6 +24,8 @@
#include <sortix/kernel/kernel.h>
#include <sortix/kernel/syscall.h>
#include "net/tcp.h"
#ifndef VERSIONSTR
#define VERSIONSTR "unknown"
#endif
@ -50,6 +52,12 @@ ssize_t sys_kernelinfo(const char* user_req, char* user_resp, size_t resplen)
char* req = GetStringFromUser(user_req);
if ( !req )
return -1;
// DEBUG
if ( !strcmp(req, "tcp") )
{
delete[] req;
return TCP::Info(user_resp, resplen);
}
#ifdef __TRACE_ALLOCATION_SITES
if ( !strcmp(req, "allocations") )
{

View File

@ -36,6 +36,7 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <assert.h>
#include <endian.h>
#include <errno.h>
@ -120,6 +121,9 @@ static kthread_mutex_t tcp_lock = KTHREAD_MUTEX_INITIALIZER;
static TCPSocket** bindings_v4;
static TCPSocket** bindings_v6;
static TCPSocket* all_first_socket;
static TCPSocket* all_last_socket;
void Init()
{
if ( !(bindings_v4 = new TCPSocket*[65536]) ||
@ -218,6 +222,7 @@ public:
int getsockname(ioctx_t* ctx, uint8_t* addr, size_t* addrsize);
public:
size_t Describe(char* buf, size_t buflen);
void Unreference();
void ProcessPacket(Ref<Packet> pkt, union tcp_sockaddr* pkt_src,
union tcp_sockaddr* pkt_dst);
@ -278,6 +283,12 @@ public:
// The listening socket this socket is in the listening queue for.
TCPSocket* connecting_parent;
// DEBUG: The previous socket of all sockets.
TCPSocket* all_prev_socket;
// DEBUG: The next socket of all sockets.
TCPSocket* all_next_socket;
// Condition variable that is signaled when new data can be received.
kthread_cond_t receive_cond;
@ -461,7 +472,7 @@ void TCPSocket__OnTimer(Clock* /*clock*/, Timer* /*timer*/, void* user)
((TCPSocket*) user)->OnTimer();
}
TCPSocket::TCPSocket(int af)
TCPSocket::TCPSocket(int af) // DEBUG: tcp_lock taken
{
prev_socket = NULL;
next_socket = NULL;
@ -517,9 +528,15 @@ TCPSocket::TCPSocket(int af)
shutdown_receive = false;
memset(incoming, 0, sizeof(incoming));
memset(outgoing, 0, sizeof(outgoing));
// DEBUG
all_prev_socket = all_last_socket;
all_next_socket = NULL;
(all_last_socket ?
all_last_socket->all_next_socket : all_first_socket) = this;
all_last_socket = this;
}
TCPSocket::~TCPSocket()
TCPSocket::~TCPSocket() // DEBUG: tcp_lock taken
{
assert(state == TCP_STATE_CLOSED);
assert(!bound);
@ -539,6 +556,52 @@ TCPSocket::~TCPSocket()
receive_queue = packet->next;
packet->next.Reset();
}
// DEBUG
(all_prev_socket ?
all_prev_socket->all_next_socket : all_first_socket) = all_next_socket;
(all_next_socket ?
all_next_socket->all_prev_socket : all_last_socket) = all_prev_socket;
all_prev_socket = NULL;
all_next_socket = NULL;
}
// DEBUG
size_t TCPSocket::Describe(char* buf, size_t buflen) // tcp_lock taken
{
const char* const STATE_NAMES[] =
{
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RECV",
"ESTAB",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT",
};
const char* state_name = STATE_NAMES[state];
char local_str[INET_ADDRSTRLEN];
char remote_str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &local.in.sin_addr, local_str, sizeof(local_str));
inet_ntop(AF_INET, &remote.in.sin_addr, remote_str, sizeof(remote_str));
char timeout[64] = "none";
if ( timer_armed )
{
struct itimerspec its;
timer.Get(&its);
snprintf(timeout, sizeof(timeout), "%ji.%09li",
(intmax_t) its.it_value.tv_sec, its.it_value.tv_nsec);
}
return snprintf(buf, buflen,
"%s %s %u -> %s %u"
" timeout=%s resends=%u sockerr=%i transmit=%i refed=%i\n",
state_name, local_str, be16toh(local.in.sin_port),
remote_str, be16toh(remote.in.sin_port), timeout,
retransmissions, sockerr, transmit_scheduled,
is_referenced);
}
void TCPSocket::Unreference()
@ -2558,6 +2621,7 @@ Ref<Inode> Socket(int af)
{
if ( !IsSupportedAddressFamily(af) )
return errno = EAFNOSUPPORT, Ref<Inode>(NULL);
ScopedLock lock(&tcp_lock); // DEBUG
TCPSocket* socket = new TCPSocket(af);
if ( !socket )
return Ref<Inode>();
@ -2567,5 +2631,45 @@ Ref<Inode> Socket(int af)
return result;
}
// DEBUG
ssize_t Info(char* user_resp, size_t resplen)
{
ScopedLock lock(&tcp_lock); // DEBUG
bool exhausted = false;
size_t total_needed = 0;
for ( TCPSocket* socket = all_first_socket;
socket;
socket = socket->all_next_socket )
{
char str[256];
size_t stringlen = socket->Describe(str, sizeof(str));
if ( !socket->all_next_socket && stringlen )
stringlen--;
total_needed += stringlen;
if ( exhausted )
continue;
if ( resplen < stringlen )
{
exhausted = true;
continue;
}
if ( !CopyToUser(user_resp, str, sizeof(char) * stringlen) )
return -1;
user_resp += stringlen;
resplen -= stringlen;
}
if ( !exhausted && !resplen )
exhausted = true;
if ( !exhausted )
{
char zero = '\0';
if ( !CopyToUser(user_resp, &zero, 1) )
return -1;
}
if ( exhausted )
return errno = ERANGE, (ssize_t) total_needed;
return 0;
}
} // namespace TCP
} // namespace Sortix

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2017 Jonas 'Sortie' Termansen.
* Copyright (c) 2016, 2017, 2022 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -34,6 +34,7 @@ void HandleIP(Ref<Packet> pkt,
const struct in_addr* dst,
bool dst_broadcast);
Ref<Inode> Socket(int af);
ssize_t Info(char* user_resp, size_t resplen);
} // namespace TCP
} // namespace Sortix