Debug TCP socket state listing.
This commit is contained in:
parent
250b95616b
commit
9d317c462e
3 changed files with 115 additions and 3 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include <sortix/kernel/syscall.h>
|
#include <sortix/kernel/syscall.h>
|
||||||
|
|
||||||
#include "kernelinfo.h"
|
#include "kernelinfo.h"
|
||||||
|
#include "net/tcp.h"
|
||||||
|
|
||||||
#ifndef VERSIONSTR
|
#ifndef VERSIONSTR
|
||||||
#define VERSIONSTR "unknown"
|
#define VERSIONSTR "unknown"
|
||||||
|
@ -55,6 +56,12 @@ ssize_t sys_kernelinfo(const char* user_req, char* user_resp, size_t resplen)
|
||||||
char* req = GetStringFromUser(user_req);
|
char* req = GetStringFromUser(user_req);
|
||||||
if ( !req )
|
if ( !req )
|
||||||
return -1;
|
return -1;
|
||||||
|
// DEBUG
|
||||||
|
if ( !strcmp(req, "tcp") )
|
||||||
|
{
|
||||||
|
delete[] req;
|
||||||
|
return TCP::Info(user_resp, resplen);
|
||||||
|
}
|
||||||
#ifdef __TRACE_ALLOCATION_SITES
|
#ifdef __TRACE_ALLOCATION_SITES
|
||||||
if ( !strcmp(req, "allocations") )
|
if ( !strcmp(req, "allocations") )
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
@ -120,6 +121,9 @@ static kthread_mutex_t tcp_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
static TCPSocket** bindings_v4;
|
static TCPSocket** bindings_v4;
|
||||||
static TCPSocket** bindings_v6;
|
static TCPSocket** bindings_v6;
|
||||||
|
|
||||||
|
static TCPSocket* all_first_socket;
|
||||||
|
static TCPSocket* all_last_socket;
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
if ( !(bindings_v4 = new TCPSocket*[65536]) ||
|
if ( !(bindings_v4 = new TCPSocket*[65536]) ||
|
||||||
|
@ -218,6 +222,7 @@ public:
|
||||||
int getsockname(ioctx_t* ctx, uint8_t* addr, size_t* addrsize);
|
int getsockname(ioctx_t* ctx, uint8_t* addr, size_t* addrsize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
size_t Describe(char* buf, size_t buflen);
|
||||||
void Unreference();
|
void Unreference();
|
||||||
void ProcessPacket(Ref<Packet> pkt, union tcp_sockaddr* pkt_src,
|
void ProcessPacket(Ref<Packet> pkt, union tcp_sockaddr* pkt_src,
|
||||||
union tcp_sockaddr* pkt_dst);
|
union tcp_sockaddr* pkt_dst);
|
||||||
|
@ -278,6 +283,12 @@ public:
|
||||||
// The listening socket this socket is in the listening queue for.
|
// The listening socket this socket is in the listening queue for.
|
||||||
TCPSocket* connecting_parent;
|
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.
|
// Condition variable that is signaled when new data can be received.
|
||||||
kthread_cond_t receive_cond;
|
kthread_cond_t receive_cond;
|
||||||
|
|
||||||
|
@ -461,7 +472,7 @@ void TCPSocket__OnTimer(Clock* /*clock*/, Timer* /*timer*/, void* user)
|
||||||
((TCPSocket*) user)->OnTimer();
|
((TCPSocket*) user)->OnTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
TCPSocket::TCPSocket(int af)
|
TCPSocket::TCPSocket(int af) // DEBUG: tcp_lock taken
|
||||||
{
|
{
|
||||||
prev_socket = NULL;
|
prev_socket = NULL;
|
||||||
next_socket = NULL;
|
next_socket = NULL;
|
||||||
|
@ -517,9 +528,15 @@ TCPSocket::TCPSocket(int af)
|
||||||
shutdown_receive = false;
|
shutdown_receive = false;
|
||||||
memset(incoming, 0, sizeof(incoming));
|
memset(incoming, 0, sizeof(incoming));
|
||||||
memset(outgoing, 0, sizeof(outgoing));
|
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(state == TCP_STATE_CLOSED);
|
||||||
assert(!bound);
|
assert(!bound);
|
||||||
|
@ -539,6 +556,52 @@ TCPSocket::~TCPSocket()
|
||||||
receive_queue = packet->next;
|
receive_queue = packet->next;
|
||||||
packet->next.Reset();
|
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()
|
void TCPSocket::Unreference()
|
||||||
|
@ -2558,6 +2621,7 @@ Ref<Inode> Socket(int af)
|
||||||
{
|
{
|
||||||
if ( !IsSupportedAddressFamily(af) )
|
if ( !IsSupportedAddressFamily(af) )
|
||||||
return errno = EAFNOSUPPORT, Ref<Inode>(NULL);
|
return errno = EAFNOSUPPORT, Ref<Inode>(NULL);
|
||||||
|
ScopedLock lock(&tcp_lock); // DEBUG
|
||||||
TCPSocket* socket = new TCPSocket(af);
|
TCPSocket* socket = new TCPSocket(af);
|
||||||
if ( !socket )
|
if ( !socket )
|
||||||
return Ref<Inode>();
|
return Ref<Inode>();
|
||||||
|
@ -2567,5 +2631,45 @@ Ref<Inode> Socket(int af)
|
||||||
return result;
|
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 TCP
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* 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,
|
const struct in_addr* dst,
|
||||||
bool dst_broadcast);
|
bool dst_broadcast);
|
||||||
Ref<Inode> Socket(int af);
|
Ref<Inode> Socket(int af);
|
||||||
|
ssize_t Info(char* user_resp, size_t resplen);
|
||||||
|
|
||||||
} // namespace TCP
|
} // namespace TCP
|
||||||
} // namespace Sortix
|
} // namespace Sortix
|
||||||
|
|
Loading…
Reference in a new issue