diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:20:54 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:20:54 +0000 |
commit | 7c720bec5600a9e607c875c670ca30ed351fa4ba (patch) | |
tree | c38c9bedf07616180feee6b91a1dbea038500b54 /src/active_hosts.cpp | |
parent | Initial commit. (diff) | |
download | iperf-upstream/2.1.9+dfsg.tar.xz iperf-upstream/2.1.9+dfsg.zip |
Adding upstream version 2.1.9+dfsg.upstream/2.1.9+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/active_hosts.cpp')
-rw-r--r-- | src/active_hosts.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/active_hosts.cpp b/src/active_hosts.cpp new file mode 100644 index 0000000..a3455ab --- /dev/null +++ b/src/active_hosts.cpp @@ -0,0 +1,261 @@ +/*--------------------------------------------------------------- + * Copyrig h(c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * active_hosts.c (was List.cpp) + * rewrite by Robert McMahon + * + * This is a list to hold active traffic and create sum groups + * sum groups are traffic sessions from the same client host + * ------------------------------------------------------------------- + */ + +#include "active_hosts.h" +#include "Mutex.h" +#include "SocketAddr.h" +#include "Reporter.h" + +/* + * Global table with active hosts, their sum reports and active thread counts + */ +static struct Iperf_Table active_table; +static bool Iperf_host_port_present (iperf_sockaddr *find); +static struct Iperf_ListEntry* Iperf_host_present (iperf_sockaddr *find); + +#if HAVE_THREAD_DEBUG +static void active_table_show_entry(const char *action, Iperf_ListEntry *entry, int found) { + assert(action != NULL); + assert(entry != NULL); + char tmpaddr[200]; + size_t len=200; + unsigned short port = SockAddr_getPort(&(entry->host)); + SockAddr_getHostAddress(&(entry->host), tmpaddr, len); + thread_debug("active table: %s %s port %d (flag=%d) rootp=%p entryp=%p totcnt/activecnt/hostcnt = %d/%d/%d", \ + action, tmpaddr, port, found, (void *) active_table.root, (void *) entry, active_table.total_count, \ + active_table.count, entry->thread_count); +} +static void active_table_show_compare(const char *action, Iperf_ListEntry *entry, iperf_sockaddr *host, const char *type) { + assert(action != NULL); + assert(entry != NULL); + char lookupaddr[200]; + char findaddr[200]; + size_t len=200; + unsigned short port = SockAddr_getPort(&(entry->host)); + unsigned short findport = SockAddr_getPort(host); + SockAddr_getHostAddress(&(entry->host), lookupaddr, len); + SockAddr_getHostAddress(host, findaddr, len); + thread_debug("active table: compare table entry %s %s/%d against host %s/%d (%s)", type, lookupaddr, port, findaddr, findport, action); +} +#endif + +void Iperf_initialize_active_table () { + Mutex_Initialize(&active_table.my_mutex); + active_table.root = NULL; + active_table.groupid = 0; +} + +/* + * Add Entry add to the list or update thread count + */ +static void active_table_update (iperf_sockaddr *host, struct thread_Settings *agent) { + assert(host != NULL); + assert(agent != NULL); + Iperf_ListEntry *this_entry = Iperf_host_present(host); + active_table.total_count++; + if (this_entry == NULL) { + this_entry = new Iperf_ListEntry(); + assert(this_entry != NULL); + this_entry->host = *host; + this_entry->next = active_table.root; + this_entry->thread_count = 1; + this_entry->socket = agent->mSock; + active_table.count++; + active_table.groupid++; + active_table.root = this_entry; + this_entry->sum_report = InitSumReport(agent, active_table.total_count, 0); + IncrSumReportRefCounter(this_entry->sum_report); + agent->mSumReport = this_entry->sum_report; + this_entry->sum_report->info.common->transferID = -active_table.groupid; // sum ids are negative +#if HAVE_THREAD_DEBUG + active_table_show_entry("new entry", this_entry, ((SockAddr_are_Equal(&this_entry->host, host) && SockAddr_Hostare_Equal(&this_entry->host, host)))); +#endif + } else { + this_entry->thread_count++; + agent->mSumReport = this_entry->sum_report; + IncrSumReportRefCounter(this_entry->sum_report); +#if HAVE_THREAD_DEBUG + active_table_show_entry("incr entry", this_entry, 1); +#endif + } +} + +static inline iperf_sockaddr *active_table_get_host_key (struct thread_Settings *agent) { + iperf_sockaddr *key = (isSumServerDstIP(agent) ? &agent->local : &agent->peer); + return key; +} + +// Thread access to store a host +int Iperf_push_host (struct thread_Settings *agent) { + iperf_sockaddr *host = active_table_get_host_key(agent); + Mutex_Lock(&active_table.my_mutex); + active_table_update(host, agent); + int groupid = active_table.groupid; + Mutex_Unlock(&active_table.my_mutex); + return groupid; +} + +// Used for UDP push of a new host, returns negative value if the host/port is already present +// This is critical because UDP is connectionless and designed to be stateless +int Iperf_push_host_port_conditional (struct thread_Settings *agent) { + iperf_sockaddr *host = active_table_get_host_key(agent); + int rc = -1; + Mutex_Lock(&active_table.my_mutex); + if (!Iperf_host_port_present(host)) { + active_table_update(host, agent); + rc = active_table.groupid; + } + Mutex_Unlock(&active_table.my_mutex); + return (rc); +} + +/* + * Remove a host from the table + */ +void Iperf_remove_host (struct thread_Settings *agent) { + iperf_sockaddr *del = active_table_get_host_key(agent); + // remove_list_entry(entry) { + // indirect = &head; + // while ((*indirect) != entry) { + // indirect = &(*indirect)->next; + // } + // *indirect = entry->next + Mutex_Lock(&active_table.my_mutex); + Iperf_ListEntry **tmp = &active_table.root; + while ((*tmp) && !(SockAddr_Hostare_Equal(&(*tmp)->host, del))) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", *tmp, del, "client ip"); +#endif + tmp = &(*tmp)->next; + } + if (*tmp) { + if (--(*tmp)->thread_count == 0) { + Iperf_ListEntry *remove = (*tmp); + active_table.count--; + agent->mSumReport = NULL; +#if HAVE_THREAD_DEBUG + active_table_show_entry("delete", remove, 1); +#endif + *tmp = remove->next; + FreeSumReport(remove->sum_report); + delete remove; + } else { + DecrSumReportRefCounter((*tmp)->sum_report); +#if HAVE_THREAD_DEBUG + active_table_show_entry("decr", (*tmp), 1); +#endif + } + } + Mutex_Unlock(&active_table.my_mutex); +} + +/* + * Destroy the table + */ +void Iperf_destroy_active_table () { + Iperf_ListEntry *itr1 = active_table.root, *itr2; + while (itr1 != NULL) { + itr2 = itr1->next; + delete itr1; + itr1 = itr2; + } + Mutex_Destroy(&active_table.my_mutex); + active_table.root = NULL; + active_table.count = 0; + active_table.total_count = 0; +} + +/* + * Check if the host and port are present in the active table + */ +bool Iperf_host_port_present (iperf_sockaddr *find) { + Iperf_ListEntry *itr = active_table.root; + bool rc = false; + while (itr != NULL) { + if (SockAddr_are_Equal(&itr->host, find)) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("match", itr, find, "client ip/port"); +#endif + rc = true; + break; + } else { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", itr, find, "client ip/port"); +#endif + itr = itr->next; + } + } + return rc; +} + +/* + * Check if the host is present in the active table + */ +static Iperf_ListEntry* Iperf_host_present (iperf_sockaddr *find) { + Iperf_ListEntry *itr = active_table.root; + while (itr != NULL) { + if (SockAddr_Hostare_Equal(&itr->host, find)) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("match", itr, find, "client ip"); +#endif + break; + } else { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", itr, find, "client ip"); +#endif + itr = itr->next; + } + } + return itr; +} |