Make a description of ${cpu} variable not so confusing.
[monky] / src / libtcp-portmon.h
index 6117e69..e38df41 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 2005  Philip Kovacs kovacsp3@comcast.net
  *
+ * $Id$
+ * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
 #ifndef LIBTCP_PORTMON_H
 #define LIBTCP_PORTMON_H
 
-#include <netdb.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+
+#include <math.h>
+#include <netdb.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
+
 #include "hash.h"
 
 /* ------------------------------------------------------------------------------------------------
  * Each port monitor contains a connection hash whose contents changes dynamically as the monitor 
  * is presented with connections on each update cycle.   This implementation maintains the health
  * of this hash by enforcing several rules.  First, the hash cannot contain more items than the
- * TCP_CONNECTION_HASH_MAX_LOAD_PCT permits.  For example, a 256 element hash with a max load of 
- * 0.5 cannot contain more than 128 connections.  Additional connections are ignored by the monitor.
+ * TCP_CONNECTION_HASH_MAX_LOAD_RATIO permits.  For example, a 512 element hash with a max load of 
+ * 0.5 cannot contain more than 256 connections.  Additional connections are ignored by the monitor.
  * The load factor of 0.5 is low enough to keep the hash running at near O(1) performanace at all 
  * times.  As elements are removed from the hash, the hash slots are tagged vacated, as required 
  * by open address hashing.  The vacated tags are essential as they enable the hash to find elements
  * The problem with vacated slots (even though they are reused) is that, as they increase in number,
  * esp. past about 1/4 of all slots, the average number of probes the hash has to perform increases
  * from O(1) on average to O(n) worst case. To keep the hash healthy, we simply rebuild it when the
- * percentage of vacated slots gets too high (above TCP_CONNECTION_HASH_MAX_VACATED_PCT).  Rebuilding
- * the hash takes O(n) on the number of elements, but it well worth it as it keeps the hash running
- * at an average access time of O(1).
+ * percentage of vacated slots gets too high (above TCP_CONNECTION_HASH_MAX_VACATED_RATIO).  
+ * Rebuilding the hash takes O(n) on the number of elements, but it well worth it as it keeps the
+ * hash running at an average access time of O(1).
  * ------------------------------------------------------------------------------------------------*/
 
-#define TCP_CONNECTION_HASH_SIZE 256                   /* connection hash size -- must be a power of two */
-#define TCP_CONNECTION_HASH_MAX_LOAD_PCT 0.5           /* disallow inserts after this % load is exceeded */
-#define TCP_CONNECIION_HASH_MAX_VACATED_PCT 0.25       /* rebalance hash after this % of vacated slots is exceeded */ 
-#define TCP_CONNECIION_STARTING_AGE 1                  /* connection deleted if unseen again after this # of refreshes */
+#define TCP_CONNECTION_HASH_SIZE_DEFAULT 512           /* connection hash size default -- must be a power of two */
+#define TCP_CONNECTION_HASH_SIZE_MAX 65536             /* connection hash size maximum -- must be a power of two */
+#define TCP_CONNECTION_HASH_MAX_LOAD_RATIO 0.5         /* disallow inserts after this load ratio is exceeded */
+#define TCP_CONNECTION_HASH_MAX_VACATED_RATIO 0.25     /* rebalance hash after this ratio of vacated slots is exceeded */ 
+#define TCP_CONNECTION_STARTING_AGE 1                  /* connection deleted if unseen again after this # of refreshes */
 
 /* ----------------------------------------------------------------------------------------
  * The tcp port monitor collection also contains a hash to track the monitors it contains.
- * This hash, unlike the connection hash describes above, is not very dynamic.  Client of
+ * This hash, unlike the connection hash describes above, is not very dynamic.  Clients of
  * this library typically create a fixed number of monitors and let them run until program 
- * termination.  For this reason, I haven't included any load governors or hash rebuilding
- * steps as is done above.  You may store up to TCP_MONITOR_HASH_SIZE monitors in this hash,
- * but you _should_ remember that keeping the load low (e.g. max of 0.5) keeps the monitor
- * lookups at O(1).  
+ * termination.  For this reason, I haven't included any hash rebuilding code as is done
+ * above.  You may store up to TCP_MONITOR_HASH_SIZE_MAX monitors in this hash, but you
+ * should remember that keeping the load low (e.g. 0.5) keeps the monitor lookups at O(1).  
  * ----------------------------------------------------------------------------------------*/
 
-/* TODO: Make TCP_CONNECTION_HASH_SIZE and TCP_MONITOR_HASH_SIZE variables the client can supply */
-
-#define TCP_MONITOR_HASH_SIZE 64                       /* monitor hash size -- must be a power of two */
+#define TCP_MONITOR_HASH_SIZE_DEFAULT 32               /* monitor hash size default -- must be a power of two */
+#define TCP_MONITOR_HASH_SIZE_MAX 512                  /* monitor hash size maximum -- must be a power of two */
+#define TCP_MONITOR_HASH_MAX_LOAD_RATIO 0.5             /* disallow new monitors after this load ratio is exceeded */
 
 /* -------------------------------------------------------------------
  * IMPLEMENTATION INTERFACE
  * ------------------------------------------------------------------- */
 
 /* The inventory of peekable items within the port monitor. */
-enum tcp_port_monitor_peekables { COUNT=0, REMOTEIP, REMOTEHOST, REMOTEPORT, LOCALIP, LOCALHOST, LOCALPORT, LOCALSERVICE };
+enum tcp_port_monitor_peekables { COUNT=0, REMOTEIP, REMOTEHOST, REMOTEPORT, REMOTESERVICE, LOCALIP, LOCALHOST, LOCALPORT, LOCALSERVICE };
 
-/* -----------------------
+/* ------------------------------------------------------------------------
  * A single tcp connection 
- * ----------------------- */
+ *
+ * The age variable provides the mechanism for removing connections if they
+ * are not seen again in subsequent update cycles.
+ * ------------------------------------------------------------------------ */
 typedef struct _tcp_connection_t {
         in_addr_t local_addr;
         in_port_t local_port;
         in_addr_t remote_addr;
         in_port_t remote_port;
-        unsigned int uid;
-        unsigned int inode;
        int age;
 } tcp_connection_t;
 
+/* ----------------------------------
+ * Copy a connection
+ *
+ * Returns 0 on success, -1 otherwise
+ * ----------------------------------*/
+int copy_tcp_connection( 
+       tcp_connection_t *                      /* p_dest_connection */,
+       const tcp_connection_t *                /* p_source_connection */
+       );
+
 /* ------------------------------------------------------------------------
  * A tcp connection node/list
  *
  * Connections within each monitor are stored in a double-linked list.
- * The age variable provides the mechanism for removing connections if they
- * are not seen again in subsequent update cycles.
  * ------------------------------------------------------------------------ */
 typedef struct _tcp_connection_node_t {
        tcp_connection_t connection;
@@ -215,6 +230,14 @@ void for_each_tcp_port_monitor_in_collection(
        void *                                  /* p_function_args (for user arguments) */
        );
 
+/* ----------------------------------------------------------------------------------------
+ * Calculate an efficient hash size based on the desired number of elements and load factor.
+ * ---------------------------------------------------------------------------------------- */
+int calc_efficient_hash_size(
+       int                                     /* min_elements, the minimum number of elements to store */,
+       int                                     /* max_hash_size, the maximum permissible hash size */,
+       double                                  /* max_load_factor, the fractional load we wish not to exceed, e.g. 0.5 */
+       );
 
 /* ----------------------------------------------------------------------
  * CLIENT INTERFACE 
@@ -222,6 +245,17 @@ void for_each_tcp_port_monitor_in_collection(
  * Clients should call only those functions below this line.
  * ---------------------------------------------------------------------- */
 
+/* struct to hold monitor creation arguments */
+typedef struct _tcp_port_monitor_args_t {
+       int     min_port_monitor_connections;   /* monitor must support tracking at least this many connections */
+} tcp_port_monitor_args_t;
+
+
+/* struct to hold collection creation arguments */
+typedef struct _tcp_port_monitor_collection_args_t {
+       int     min_port_monitors;              /* collection must support creation of at least this many monitors */
+} tcp_port_monitor_collection_args_t; 
+
 /* ----------------------------------
  * Client operations on port monitors
  * ---------------------------------- */
@@ -230,14 +264,15 @@ void for_each_tcp_port_monitor_in_collection(
    so that there are no redundant monitors. */
 tcp_port_monitor_t * create_tcp_port_monitor(
        in_port_t                               /* port_range_begin */, 
-       in_port_t                               /* port_range_end */ 
+       in_port_t                               /* port_range_end */,
+       tcp_port_monitor_args_t *               /* p_creation_args, NULL ok for library defaults */
        );
 
 /* Clients use this function to get connection data from the indicated port monitor.
    The requested monitor value is copied into a client-supplied char buffer. 
    Returns 0 on success, -1 otherwise. */
 int peek_tcp_port_monitor(
-       tcp_port_monitor_t *                    /* p_monitor */,
+       const tcp_port_monitor_t *              /* p_monitor */,
        int                                     /* item, ( item of interest, from tcp_port_monitor_peekables enum ) */,
        int                                     /* connection_index, ( 0 to number of connections in monitor - 1 )*/,
        char *                                  /* p_buffer, buffer to receive requested value */,
@@ -249,7 +284,9 @@ int peek_tcp_port_monitor(
  * -------------------------------- */
 
 /* Create a monitor collection.  Do this one first. */
-tcp_port_monitor_collection_t * create_tcp_port_monitor_collection( void );
+tcp_port_monitor_collection_t * create_tcp_port_monitor_collection(
+       tcp_port_monitor_collection_args_t *    /* p_creation_args, NULL ok for library defaults */
+       );
 
 /* Destroy the monitor collection (and everything it contains).  Do this one last. */
 void destroy_tcp_port_monitor_collection( 
@@ -270,7 +307,7 @@ int insert_tcp_port_monitor_into_collection(
 
 /* Clients need a way to find monitors */
 tcp_port_monitor_t * find_tcp_port_monitor( 
-       tcp_port_monitor_collection_t *         /* p_collection */, 
+       const tcp_port_monitor_collection_t *   /* p_collection */, 
        in_port_t                               /* port_range_begin */, 
        in_port_t                               /* port_range_end */ 
        );