LCOV - code coverage report
Current view: top level - src - ConnCompressor.h (source / functions) Hit Total Coverage
Test: app.info Lines: 25 32 78.1 %
Date: 2010-12-13 Functions: 15 18 83.3 %
Branches: 15 26 57.7 %

           Branch data     Line data    Source code
       1                 :            : // $Id: ConnCompressor.h 6008 2008-07-23 00:24:22Z vern $
       2                 :            : //
       3                 :            : // The ConnCompressor keeps track of the first packet seen for a conn_id using
       4                 :            : // only a minimal amount of memory. This helps us to avoid instantiating
       5                 :            : // full Connection objects for never-established sessions.
       6                 :            : //
       7                 :            : // TCP only.
       8                 :            : 
       9                 :            : #ifndef CONNCOMPRESSOR_H
      10                 :            : #define CONNCOMPRESSOR_H
      11                 :            : 
      12                 :            : #include "Conn.h"
      13                 :            : #include "Dict.h"
      14                 :            : #include "NetVar.h"
      15                 :            : #include "TCP.h"
      16                 :            : 
      17                 :            : class ConnCompressor {
      18                 :            : public:
      19                 :            :         ConnCompressor();
      20                 :            :         ~ConnCompressor();
      21                 :            : 
      22                 :            :         // Handle next packet.  Returns 0 if packet in handled internally.
      23                 :            :         // Takes ownership of key.
      24                 :            :         Connection* NextPacket(double t, HashKey* k, const IP_Hdr* ip_hdr,
      25                 :            :                         const struct pcap_pkthdr* hdr, const u_char* const pkt);
      26                 :            : 
      27                 :            :         // Look up a connection.  Returns non-nil for connections for
      28                 :            :         // which a Connection object has already been instantiated.
      29                 :          8 :         Connection* Lookup(HashKey* k)
      30                 :            :                 {
      31                 :          8 :                 ConnData* c = conns.Lookup(k);
      32   [ +  -  +  - ]:          8 :                 return c && IsConnPtr(c) ? MakeConnPtr(c) : 0;
      33                 :            :                 }
      34                 :            : 
      35                 :            :         // Inserts connection into compressor.  If another entry with this key
      36                 :            :         // already exists, it's replaced.  If that was a full connection, it is
      37                 :            :         // also returned.
      38                 :            :         Connection* Insert(Connection* c);
      39                 :            : 
      40                 :            :         // Remove all state belonging to the given connection.  Returns
      41                 :            :         // true if the connection was found in the compressor's table,
      42                 :            :         // false if not.
      43                 :            :         bool Remove(HashKey* k);
      44                 :            : 
      45                 :            :         // Flush state.
      46                 :            :         void Drain();
      47                 :            : 
      48                 :            :         struct Sizes {
      49                 :            :                 // Current number of already fully instantiated connections.
      50                 :            :                 unsigned int connections;
      51                 :            : 
      52                 :            :                 // Total number of fully instantiated connections.
      53                 :            :                 unsigned int connections_total;
      54                 :            : 
      55                 :            :                 // Current number of seen but non-yet instantiated connections.
      56                 :            :                 unsigned int pending_valid;
      57                 :            : 
      58                 :            :                 // Total number of seen but non-yet instantiated connections.
      59                 :            :                 unsigned int pending_total;
      60                 :            : 
      61                 :            :                 // Total number of all entries in pending list (some a which
      62                 :            :                 // may already been invalid, but not yet removed from memory).
      63                 :            :                 unsigned int pending_in_mem;
      64                 :            : 
      65                 :            :                 // Total number of hash table entires
      66                 :            :                 // (should equal connections + pending_valid)
      67                 :            :                 unsigned int hash_table_size;
      68                 :            : 
      69                 :            :                 // Total memory usage;
      70                 :            :                 unsigned int memory;
      71                 :            :         };
      72                 :            : 
      73                 :          0 :         const Sizes& Size()
      74                 :          0 :                 { sizes.hash_table_size = conns.Length(); return sizes; }
      75                 :            : 
      76                 :            :         unsigned int MemoryAllocation() const   { return sizes.memory; }
      77                 :            : 
      78                 :            :         // As long as we have only seen packets from one side, we just
      79                 :            :         // store a PendingConn.
      80                 :            :         struct PendingConn {
      81                 :            :                 // True if the block is indeed a PendingConn (see below).
      82                 :            :                 unsigned int is_pending:1;
      83                 :            : 
      84                 :            :                 // Whether roles in key are flipped.
      85                 :            :                 unsigned int ip1_is_src:1;
      86                 :            : 
      87                 :            :                 unsigned int invalid:1; // deleted
      88                 :            :                 int window_scale:4;
      89                 :            :                 unsigned int SYN:1;
      90                 :            :                 unsigned int FIN:1;
      91                 :            :                 unsigned int RST:1;
      92                 :            :                 unsigned int ACK:1;
      93                 :            : 
      94                 :            :                 double time;
      95                 :            :                 ConnID::Key key;
      96                 :            :                 uint32 seq;
      97                 :            :                 uint32 ack;
      98                 :            :                 hash_t hash;
      99                 :            :                 uint16 window;
     100                 :            :         };
     101                 :            : 
     102                 :            : private:
     103                 :            :         // Helpers to extract addrs/ports from PendingConn.
     104                 :            : 
     105                 :       2235 :         const uint32* SrcAddr(const PendingConn* c)
     106         [ +  + ]:       2235 :                 { return c->ip1_is_src ? c->key.ip1 : c->key.ip2; }
     107                 :       1214 :         const uint32* DstAddr(const PendingConn* c)
     108         [ +  + ]:       1214 :                 { return c->ip1_is_src ? c->key.ip2 : c->key.ip1; }
     109                 :            : 
     110                 :       2401 :         uint16 SrcPort(const PendingConn* c)
     111         [ +  + ]:       2401 :                 { return c->ip1_is_src ? c->key.port1 : c->key.port2; }
     112                 :       1904 :         uint16 DstPort(const PendingConn* c)
     113         [ +  + ]:       1904 :                 { return c->ip1_is_src ? c->key.port2 : c->key.port1; }
     114                 :            : 
     115                 :            : 
     116                 :            :         // Called for the first packet in a connection.
     117                 :            :         Connection* FirstFromOrig(double t, HashKey* key,
     118                 :            :                                         const IP_Hdr* ip, const tcphdr* tp);
     119                 :            : 
     120                 :            :         // Called for more packets from the orginator w/o seeing a response.
     121                 :            :         Connection* NextFromOrig(PendingConn* pending,
     122                 :            :                                 double t, HashKey* key, const tcphdr* tp);
     123                 :            : 
     124                 :            :         // Called for the first response packet. Instantiates a Connection.
     125                 :            :         Connection* Response(PendingConn* pending, double t, HashKey* key,
     126                 :            :                                         const IP_Hdr* ip, const tcphdr* tp);
     127                 :            : 
     128                 :            :         // Instantiates a full TCP connection (invalidates pending connection).
     129                 :            :         Connection* Instantiate(HashKey* key, PendingConn* pending);
     130                 :            : 
     131                 :            :         // Same but based on packet.
     132                 :            :         Connection* Instantiate(double t, HashKey* key, const IP_Hdr* ip);
     133                 :            : 
     134                 :            :         // Fills the attributes of a PendingConn based on the given arguments.
     135                 :            :         void PktHdrToPendingConn(double time, const HashKey* key,
     136                 :            :                 const IP_Hdr* ip, const struct tcphdr* tp, PendingConn* c);
     137                 :            : 
     138                 :            :         // Fakes a TCP packet based on the available information.
     139                 :            :         const IP_Hdr* PendingConnToPacket(const PendingConn* c);
     140                 :            : 
     141                 :            :         // For changing the timestamp of PendingConn - allocates a new one,
     142                 :            :         // sets the given time, and copies all other data from old.
     143                 :            :         PendingConn* MoveState(double time, PendingConn* old);
     144                 :            : 
     145                 :            :         // Construct a TCP-flags byte.
     146                 :            :         uint8 MakeFlags(const PendingConn* c) const;
     147                 :            : 
     148                 :            :         // Allocate room for a new (Ext)PendingConn.
     149                 :            :         PendingConn* MakeNewState(double t);
     150                 :            : 
     151                 :            :         // Expire PendingConns.
     152                 :            :         void DoExpire(double t);
     153                 :            : 
     154                 :            :         // Remove all state belonging to the given connection.
     155                 :            :         void Invalidate(HashKey* k);
     156                 :            : 
     157                 :            :         // Sends the given connection_* event.  If orig_state is
     158                 :            :         // TCP_ENDPOINT__INACTIVE, tries to guess a better one based
     159                 :            :         // on pending.  If arg in non-nil, it will be used as the
     160                 :            :         // *first* argument of the event call (this is for conn_weird()).
     161                 :            :         void Event(const PendingConn* pending, double t,
     162                 :            :                         const EventHandlerPtr& event, int orig_state,
     163                 :            :                         int orig_size, int resp_state, Val* arg = 0);
     164                 :            : 
     165                 :          0 :         void Weird(const PendingConn* pending, double t, const char* msg)
     166                 :            :                 {
     167         [ #  # ]:          0 :                 if ( conn_weird )
     168                 :            :                         Event(pending, t, conn_weird, TCP_ENDPOINT_INACTIVE, 0,
     169                 :          0 :                                 TCP_ENDPOINT_INACTIVE, new StringVal(msg));
     170                 :            :                 else
     171                 :          0 :                         fprintf(stderr, "%.06f weird: %s\n", t, msg);
     172                 :          0 :                 }
     173                 :            : 
     174                 :            :         static const int BLOCK_SIZE = 16 * 1024;
     175                 :            : 
     176                 :            :         // The memory managment for PendConns.
     177                 :            :         struct Block {
     178                 :            :                 double time;
     179                 :            :                 Block* prev;
     180                 :            :                 Block* next;
     181                 :            :                 int bytes_used;
     182                 :            :                 unsigned char data[BLOCK_SIZE];
     183                 :            :         };
     184                 :            : 
     185                 :            :         // In the connection hash table, we store pointers to both PendingConns
     186                 :            :         // and Connections. Thus, we need a way to differentiate between
     187                 :            :         // these two types. To avoid an additional indirection, we use a little
     188                 :            :         // hack: a pointer retrieved from the table is interpreted as a
     189                 :            :         // PendingConn first. However, if is_pending is false, it's in fact a
     190                 :            :         // Connection which starts at offset 4. The methods below help to
     191                 :            :         // implement this scheme transparently. An "operator new" in
     192                 :            :         // Connection takes care of building Connection's accordingly.
     193                 :            :         typedef PendingConn ConnData;
     194 [ -  + ][ #  # ]:      20526 :         declare(PDict, ConnData);
     195                 :            :         typedef PDict(ConnData) ConnMap;
     196                 :            :         ConnMap conns;
     197                 :            : 
     198                 :        676 :         static ConnData* MakeMapPtr(PendingConn* c)
     199         [ -  + ]:        676 :                 { assert(c->is_pending); return c; }
     200                 :            : 
     201                 :        938 :         static ConnData* MakeMapPtr(Connection* c)
     202                 :            :                 {
     203                 :        938 :                 ConnData* p = (ConnData*) (((char*) c) - 4);
     204         [ -  + ]:        938 :                 assert(!p->is_pending);
     205                 :        938 :                 return p;
     206                 :            :                 }
     207                 :            : 
     208                 :       1043 :         static PendingConn* MakePendingConnPtr(ConnData* c)
     209         [ -  + ]:       1043 :                 { assert(c->is_pending); return c; }
     210                 :            : 
     211                 :      17474 :         static Connection* MakeConnPtr(ConnData* c)
     212                 :            :                 {
     213         [ -  + ]:      17474 :                 assert(!c->is_pending);
     214                 :      17474 :                 return (Connection*) (((char*) c) + 4);
     215                 :            :                 }
     216                 :            : 
     217                 :      18578 :         static bool IsConnPtr(ConnData* c)
     218                 :      18578 :                 { return ! c->is_pending; }
     219                 :            : 
     220                 :            :         // New blocks are inserted at the end.
     221                 :            :         Block* first_block;
     222                 :            :         Block* last_block;
     223                 :            : 
     224                 :            :         // If we have already expired some entries in a block,
     225                 :            :         // this points to the first non-expired.
     226                 :            :         unsigned char* first_non_expired;
     227                 :            : 
     228                 :            :         // Last "connection" that we have build.
     229                 :            :         RecordVal* conn_val;
     230                 :            : 
     231                 :            :         // Statistics.
     232                 :            :         Sizes sizes;
     233                 :            :         };
     234                 :            : 
     235                 :            : extern ConnCompressor* conn_compressor;
     236                 :            : 
     237                 :            : #endif

Generated by: LCOV version 1.8