// -*- c-basic-offset: 4 -*-
#ifndef CLICK_AGGREGATEIPADDRPAIR_HH
#define CLICK_AGGREGATEIPADDRPAIR_HH
#include <click/element.hh>
#include <click/hashmap.hh>
#include "aggregatenotifier.hh"
CLICK_DECLS

/*
=c

AggregateIPAddrPair(I<KEYWORDS>)

=s ipmeasure

sets aggregate annotation based on IP source/destination address pair

=d

AggregateIPAddrPair sets the aggregate annotation on every passing packet to a
flow number based on its IP address pair.  Packets with the same
source-destination address pair are assigned the same aggregate number, as are
reply packets (with source and destination addresses switched).  The paint
annotation is set to 0 or 1 to indicate which direction the packet was headed.

Flow numbers are assigned sequentially, starting from 1. Different flows get
different numbers. Paint annotations are set to 0 or 1, depending on whether
packets are on the forward or reverse subflow. (The first packet seen on each
flow gets paint color 0; reply packets get paint color 1.)

Keywords are:

=over 8

=item TIMEOUT

The timeout for active address pairs, in seconds.  Default is no timeout
(address pairs never expire).  If a timeout is specified, then information
about an address pair is forgotten after that timeout passes; if the address
pair occurs again later, it will get a new aggregate annotation.

=item REAP

The garbage collection interval. Default is 20 minutes of packet time.

=back

AggregateIPAddrPair is an AggregateNotifier, so AggregateListeners can request
notifications when new aggregates are created and old ones are deleted.

=h clear write-only

Clears all flow information.  Future packets will get new aggregate annotation
values.
   
=a

AggregateIPFlows, AggregateCounter, AggregateIP
*/

class AggregateIPAddrPair : public Element, public AggregateNotifier { public:

    AggregateIPAddrPair();
    ~AggregateIPAddrPair();

    const char *class_name() const	{ return "AggregateIPAddrPair"; }
    const char *port_count() const	{ return "1/1-2"; }
    const char *processing() const	{ return "a/ah"; }
    void *cast(const char *);

    int configure(Vector<String> &, ErrorHandler *);
    int initialize(ErrorHandler *);
    void add_handlers();

    Packet *simple_action(Packet *);

    struct HostPair {
	uint32_t a;
	uint32_t b;
	HostPair() : a(0), b(0) { }
	HostPair(uint32_t aa, uint32_t bb) : a(aa), b(bb) { if (a > b) a ^= b ^= a ^= b; }
    };
    
  private:

    struct FlowInfo {
	Timestamp last_timestamp;
	uint32_t aggregate;
	bool reverse;
	FlowInfo()		: aggregate(0) { }
    };
    
    typedef HashMap<HostPair, FlowInfo> Map;
    Map _map;

    unsigned _active_sec;
    unsigned _gc_sec;
    
    int _timeout;
    unsigned _gc_interval;
    bool _timestamp_warning;
    uint32_t _next;

    void reap();

    static int write_handler(const String &, Element *, void *, ErrorHandler *);
    
};

CLICK_ENDDECLS
#endif


syntax highlighted by Code2HTML, v. 0.9.1