From 1e82d88906576c82db489a6462cedbacde5d4c96 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 1 Jun 2022 11:08:06 +0200 Subject: [PATCH] Debug TCP socket state listing. --- kernel/kernelinfo.cpp | 8 ++++ kernel/net/tcp.cpp | 108 +++++++++++++++++++++++++++++++++++++++++- kernel/net/tcp.h | 3 +- 3 files changed, 116 insertions(+), 3 deletions(-) diff --git a/kernel/kernelinfo.cpp b/kernel/kernelinfo.cpp index aeaf07e6..8f639dfc 100644 --- a/kernel/kernelinfo.cpp +++ b/kernel/kernelinfo.cpp @@ -24,6 +24,8 @@ #include #include +#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") ) { diff --git a/kernel/net/tcp.cpp b/kernel/net/tcp.cpp index c3371f67..aa5c33a8 100644 --- a/kernel/net/tcp.cpp +++ b/kernel/net/tcp.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -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 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 Socket(int af) { if ( !IsSupportedAddressFamily(af) ) return errno = EAFNOSUPPORT, Ref(NULL); + ScopedLock lock(&tcp_lock); // DEBUG TCPSocket* socket = new TCPSocket(af); if ( !socket ) return Ref(); @@ -2567,5 +2631,45 @@ Ref 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 diff --git a/kernel/net/tcp.h b/kernel/net/tcp.h index 2c7d8e81..92b33833 100644 --- a/kernel/net/tcp.h +++ b/kernel/net/tcp.h @@ -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 pkt, const struct in_addr* dst, bool dst_broadcast); Ref Socket(int af); +ssize_t Info(char* user_resp, size_t resplen); } // namespace TCP } // namespace Sortix