summaryrefslogtreecommitdiffstats
path: root/src/active_hosts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/active_hosts.cpp')
-rw-r--r--src/active_hosts.cpp261
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;
+}