/*
** SellaNMS
** $Id: icmp.h,v 2.52 2005/05/15 05:21:17 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

#ifndef __DGS_MODULE_MONITOR_ICMP_H
#define __DGS_MODULE_MONITOR_ICMP_H

#ifdef HAVE_CONFIG_H
	#include "config.h"
#endif

#include "defaults.h"
#include "util.h"
#include "netblock.h"
#include "storagedata.h"
#include "../monitor.h"
#include "policy_framework/policy_framework.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <stl/list>
#include <stl/queue>
#include <stl/list>
#include <stl/string>

#define MODULE_MONITOR_ICMP_QUEUEDEPTHMIN_DEFAULT 250
#define MODULE_MONITOR_ICMP_CALCQUEUEDEPTH_DEFAULT 1000
#define MODULE_MONITOR_ICMP_POLICYQUEUEDEPTH_MULTIPLIER 8
#define MODULE_MONITOR_ICMP_CALCINTERVAL_DEFAULT 30
#define MODULE_MONITOR_ICMP_CALCINTERVALADJ_DEFAULT 5
#define MODULE_MONITOR_ICMP_TRANSMIT_DEFAULT 3
#define MODULE_MONITOR_ICMP_INTERVAL_DEFAULT 60
#define MODULE_MONITOR_ICMP_MAXRTT_DEFAULT 1000
#define MODULE_MONITOR_ICMP_MAXRTT_MAXIMUM 9999
#define MODULE_MONITOR_ICMP_MAXNRM_DEFAULT 10000000
#define MODULE_MONITOR_ICMP_SEQUENCEMAXADJ_DEFAULT 48
#define MODULE_MONITOR_ICMP_PAYLOADMESSAGE_DEFAULT "SellaNMS - ICMP Monitor Module"
#define MODULE_MONITOR_ICMP_SOURCE_DEFAULT ""
#define MODULE_MONITOR_ICMP_TOS_DEFAULT MODULE_MONITOR_TOS_DEFAULT
#define MODULE_MONITOR_ICMP_TTL_DEFAULT IPDEFTTL

#define MODULE_MONITOR_ICMP_LOSSSUPVAR_DEFAULT 5
#define MODULE_MONITOR_ICMP_RTTSUPVAR_DEFAULT 30
#define MODULE_MONITOR_ICMP_JTRSUPVAR_DEFAULT 30
#define MODULE_MONITOR_ICMP_NRMSUPVAR_DEFAULT 30

#define FLAG_CALC_LOSS (0x1 << 0)
#define FLAG_CALC_LTCY (0x1 << 1)
#define FLAG_CALC_JTTR (0x1 << 2)
#define FLAG_CALC_NORM (0x1 << 3)
#define FLAG_CALC_TOSC (0x1 << 4)

typedef struct icmp_payload	{
	in_addr		source;
	in_addr		destination;
	u_int16_t	sequence;
	timeval		stamp;
	
	char		message[36];
};

/* Calculation Thread's Queue (Used between recieve and calc thread) */
typedef struct _calc_queue_data_t {
	u_int32_t address;

	timeval timestamp;
	timeval rtt;

	int8_t type;
	int8_t code;

	u_int8_t tos;
} calc_queue_entry_t;
typedef queue<calc_queue_entry_t> calc_queue_t;

/* Policy Thread's Queue (Used between calc policy thread) */
typedef struct _policy_queue_entry_t {
	u_int32_t address;

	u_int32_t interval;

	int8_t type;
	int8_t code;

	u_int8_t tos;

	int8_t loss; //Packet Loss percentage for interval.

	u_int16_t min_rtt; //Minimum RTT for interval.
	u_int16_t max_rtt; //Maximum RTT for interval.
	u_int16_t avg_rtt; //Average RTT for interval.

	u_int16_t min_jtr; //Minimum Jitter for interval.
	u_int16_t max_jtr; //Maximum Jitter for interval.
	u_int16_t avg_jtr; //Average Jitter for interval.

	u_int16_t nrm_rtt; //Normalized RTT (moving average)
	u_int16_t nrm_var_abs; //Normalized RTT variation from average abs(avg_rtt - nrm_rtt)
	u_int16_t nrm_var_inc; //Normalized RTT variation from average inc(avg_rtt - nrm_rtt)
	u_int16_t nrm_var_dec; //Normalized RTT variation from average dec(avg_rtt - nrm_rtt)
	u_int16_t nrm_per_abs; //Normalized RTT variation percentage abs(nrm_rtt/avg_rtt * 100)
	u_int16_t nrm_per_inc; //Normalized RTT variation percentage inc(nrm_rtt/avg_rtt * 100)
	u_int16_t nrm_per_dec; //Normalized RTT variation percentage dec(nrm_rtt/avg_rtt * 100)
} policy_queue_entry_t;
typedef queue<policy_queue_entry_t> policy_queue_t;

/* Calculation Thread's Internal Data Structure */
typedef struct _calc_data_entry_t {
	timeval timestamp;
	timeval rtt;

	int8_t type;
	int8_t code;

	u_int8_t tos;
} calc_data_entry_t;
typedef slist<calc_data_entry_t> calc_data_entry_list_t;
typedef hash_map<u_int32_t, pair<u_int32_t, u_int16_t> > nrm_rtt_hash_t;

typedef hash_map<u_int32_t, calc_data_entry_list_t> calc_data_t;
typedef hash_map<u_int32_t, hash_map<u_int32_t, policy_queue_entry_t> > calc_data_sup_t;

typedef struct _transmit_entry_t {
	u_int32_t	address;

	u_int16_t	sequence;
	timeval		timestamp;
} transmit_entry_t;

typedef slist<transmit_entry_t> transmit_list_t;
typedef hash_map<pair<u_int32_t, int>, transmit_list_t::iterator, hash<pair<u_int32_t, int> > > transmit_hash_t;

class ICMP: public Monitor {
	public:
		ICMP();
		~ICMP();

	protected:
		RESULT sleep(unsigned long t, unsigned long &accuracy);

		RESULT initPacket(char *packet, unsigned long size);
		RESULT transmitPacket(int s, char *packet, unsigned long size);
		RESULT watchNetwork(int s);
		RESULT calculateChecksum(char *packet, unsigned long size);

		RESULT pollTargets(int s, char *packet, timeval *interval);

		unsigned long	sleepIndex;
		unsigned long	sleepSample[8];	

	private:
		virtual RESULT execute();
		virtual RESULT readConfig();
		virtual RESULT printConfig();

		static RESULT transmit_thread(void *args);
		static RESULT receive_thread(void *args);
		static RESULT timeout_thread(void *args);
		static RESULT policy_thread(void *args);
		static RESULT calc_thread(void *args);

		RESULT calculate(slist<unsigned int> &interval_list);
		bool suppressDuplicate(const policy_queue_entry_t &policy_queue_entry);
		RESULT getPolicyIntervals(slist<unsigned int> &interval_list);
		RESULT setPolicyInputEventData(variable_binding_t *policy_input, char* event, unsigned long value);
		RESULT setPolicyInputTypeCode(variable_binding_t *policy_input, int8_t type, int8_t code);
		RESULT updateStatus();

		bool					ignoreEdge;
		bool					throttle;
		bool					suppression;

		uint32_t				source;
		string				payloadMessage;

		unsigned long		module_id;
		unsigned long		transmit;
		unsigned long		interval;
		struct timeval		maxRTT;

		calc_queue_t		calc_queue;
		policy_queue_t		policy_queue;
		pthread_mutex_t	calc_queue_mutex;
		pthread_mutex_t	policy_queue_mutex;

		calc_data_t			calc_data;
		calc_data_sup_t	calc_data_sup;
		pthread_mutex_t	calc_data_mutex;

		transmit_list_t	transmit_list;
		transmit_hash_t	transmit_hash;
		pthread_mutex_t	transmit_mutex;

		hash_map<u_int32_t, string> status_hash;
		pthread_mutex_t	status_mutex;

		unsigned long calcQueueDepth;
		unsigned long policyQueueDepth;
		unsigned long calcInterval;
		unsigned long calcIntervalAdj;
		unsigned long calcFlags;
		unsigned long policyQueueLimitMax;
		unsigned long ttl;
		unsigned long lossSupVar;
		unsigned long rttSupVar;
		unsigned long jtrSupVar;
		unsigned long nrmSupVar;

		int				calc_flag[2];
		int				policy_flag[2];
};

#endif

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim600: fdm=marker
** vim: noet ts=3 sw=3
*/
