⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aggregateipflows.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * aggregateipflows.{cc,hh} -- set aggregate annotation based on TCP/UDP flow * Eddie Kohler * * Copyright (c) 2001-2003 International Computer Science Institute * Copyright (c) 2005-2008 Regents of the University of California * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "aggregateipflows.hh"#include <click/error.hh>#include <click/hashmap.hh>#include <click/straccum.hh>#include <click/confparse.hh>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>#include <clicknet/icmp.h>#include <click/packet_anno.hh>#include <click/handlercall.hh>CLICK_DECLS#define SEC_OLDER(s1, s2)	((int)(s1 - s2) < 0)// operations on host pairs and ports valuesstatic inline const click_ip *good_ip_header(const Packet *p){    // called when we already know the packet is good    const click_ip *iph = p->ip_header();    if (iph->ip_p == IP_PROTO_ICMP)	return reinterpret_cast<const click_ip *>(p->icmp_header() + 1); // know it exists    else	return iph;}static inline booloperator==(const AggregateIPFlows::HostPair &a, const AggregateIPFlows::HostPair &b){    return a.a == b.a && a.b == b.b;}inline hashcode_tAggregateIPFlows::HostPair::hashcode() const{    return (a << 12) + b + ((a >> 20) & 0x1F);}static inline boolports_reverse_order(uint32_t ports){    return (int32_t) ((ports << 16) - ports) < 0;}static inline uint32_tflip_ports(uint32_t ports){    return ((ports >> 16) & 0xFFFF) | (ports << 16);}// actual AggregateIPFlows operationsAggregateIPFlows::AggregateIPFlows()#if CLICK_USERLEVEL    : _traceinfo_file(0), _packet_source(0), _filepos_h(0)#endif{}AggregateIPFlows::~AggregateIPFlows(){}void *AggregateIPFlows::cast(const char *n){    if (strcmp(n, "AggregateNotifier") == 0)	return (AggregateNotifier *)this;    else if (strcmp(n, "AggregateIPFlows") == 0)	return (Element *)this;    else	return Element::cast(n);}intAggregateIPFlows::configure(Vector<String> &conf, ErrorHandler *errh){    _tcp_timeout = 24 * 60 * 60;    _tcp_done_timeout = 30;    _udp_timeout = 60;    _fragment_timeout = 30;    _gc_interval = 20 * 60;    _fragments = 2;    bool handle_icmp_errors = false;    bool gave_fragments = false, fragments = true;    if (cp_va_kparse(conf, this, errh,		     "TCP_TIMEOUT", 0, cpSeconds, &_tcp_timeout,		     "TCP_DONE_TIMEOUT", 0, cpSeconds, &_tcp_done_timeout,		     "UDP_TIMEOUT", 0, cpSeconds, &_udp_timeout,		     "FRAGMENT_TIMEOUT", 0, cpSeconds, &_fragment_timeout,		     "REAP", 0, cpSeconds, &_gc_interval,		     "ICMP", 0, cpBool, &handle_icmp_errors,#if CLICK_USERLEVEL		     "TRACEINFO", 0, cpFilename, &_traceinfo_filename,		     "SOURCE", 0, cpElement, &_packet_source,#endif		     "FRAGMENTS", cpkC, &gave_fragments, cpBool, &fragments,		     cpEnd) < 0)	return -1;    _smallest_timeout = (_tcp_timeout < _tcp_done_timeout ? _tcp_timeout : _tcp_done_timeout);    _smallest_timeout = (_smallest_timeout < _udp_timeout ? _smallest_timeout : _udp_timeout);    _handle_icmp_errors = handle_icmp_errors;    if (gave_fragments)	_fragments = fragments;    return 0;}intAggregateIPFlows::initialize(ErrorHandler *errh){    _next = 1;    _active_sec = _gc_sec = 0;    _timestamp_warning = false;#if CLICK_USERLEVEL    if (_traceinfo_filename == "-")	_traceinfo_file = stdout;    else if (_traceinfo_filename && !(_traceinfo_file = fopen(_traceinfo_filename.c_str(), "w")))	return errh->error("%s: %s", _traceinfo_filename.c_str(), strerror(errno));    if (_traceinfo_file) {	fprintf(_traceinfo_file, "<?xml version='1.0' standalone='yes'?>\n\<trace");	if (_packet_source) {	    if (String s = HandlerCall::call_read(_packet_source, "filename").trim_space())		fprintf(_traceinfo_file, " file='%s'", s.c_str());	    (void) HandlerCall::reset_read(_filepos_h, _packet_source, "packet_filepos");	}	fprintf(_traceinfo_file, ">\n");    }#endif    if (_fragments == 2)	_fragments = !input_is_pull(0);    else if (_fragments == 1 && input_is_pull(0))	return errh->error("'FRAGMENTS true' is incompatible with pull; run this element in a push context");    return 0;}voidAggregateIPFlows::cleanup(CleanupStage){    clean_map(_tcp_map);    clean_map(_udp_map);#if CLICK_USERLEVEL    if (_traceinfo_file && _traceinfo_file != stdout) {	fprintf(_traceinfo_file, "</trace>\n");	fclose(_traceinfo_file);    }    delete _filepos_h;#endif}inline voidAggregateIPFlows::delete_flowinfo(const HostPair &hp, FlowInfo *finfo, bool really_delete){#if CLICK_USERLEVEL    if (_traceinfo_file) {	StatFlowInfo *sinfo = static_cast<StatFlowInfo *>(finfo);	IPAddress src(sinfo->reverse() ? hp.b : hp.a);	int sport = (ntohl(sinfo->_ports) >> (sinfo->reverse() ? 0 : 16)) & 0xFFFF;	IPAddress dst(sinfo->reverse() ? hp.a : hp.b);	int dport = (ntohl(sinfo->_ports) >> (sinfo->reverse() ? 16 : 0)) & 0xFFFF;	Timestamp duration = sinfo->_last_timestamp - sinfo->_first_timestamp;	fprintf(_traceinfo_file, "<flow aggregate='%u' src='%s' sport='%d' dst='%s' dport='%d' begin='" PRITIMESTAMP "' duration='" PRITIMESTAMP "'",		sinfo->_aggregate,		src.unparse().c_str(), sport, dst.unparse().c_str(), dport,		sinfo->_first_timestamp.sec(), sinfo->_first_timestamp.subsec(),		duration.sec(), duration.subsec());	if (sinfo->_filepos)	    fprintf(_traceinfo_file, " filepos='%u'", sinfo->_filepos);	fprintf(_traceinfo_file, ">\n\  <stream dir='0' packets='%d' /><stream dir='1' packets='%d' />\n\</flow>\n",		sinfo->_packets[0], sinfo->_packets[1]);	if (really_delete)	    delete sinfo;    } else#endif	if (really_delete)	    delete finfo;}voidAggregateIPFlows::clean_map(Map &table){    // free completed flows and emit fragments    for (Map::iterator iter = table.begin(); iter.live(); iter++) {	HostPairInfo *hpinfo = &iter.value();	while (Packet *p = hpinfo->_fragment_head) {	    hpinfo->_fragment_head = p->next();	    p->kill();	}	while (FlowInfo *f = hpinfo->_flows) {	    hpinfo->_flows = f->_next;	    delete_flowinfo(iter.key(), f);	}    }}#if CLICK_USERLEVELvoidAggregateIPFlows::stat_new_flow_hook(const Packet *p, FlowInfo *finfo){    StatFlowInfo *sinfo = static_cast<StatFlowInfo *>(finfo);    sinfo->_first_timestamp = p->timestamp_anno();    sinfo->_filepos = 0;    if (_filepos_h)	(void) cp_integer(_filepos_h->call_read().trim_space(), &sinfo->_filepos);}#endifinline voidAggregateIPFlows::packet_emit_hook(const Packet *p, const click_ip *iph, FlowInfo *finfo){    // account for timestamp    finfo->_last_timestamp = p->timestamp_anno();    // check whether this indicates the flow is over    if (iph->ip_p == IP_PROTO_TCP && IP_FIRSTFRAG(iph)	/* 3.Feb.2004 - NLANR dumps do not contain full TCP headers! So relax	   the following length check to just make sure the flags are	   there. */	&& p->transport_length() >= 14	&& PAINT_ANNO(p) < 2) {	// ignore ICMP errors	if (p->tcp_header()->th_flags & TH_RST)	    finfo->_flow_over = 3;	else if (p->tcp_header()->th_flags & TH_FIN)	    finfo->_flow_over |= (1 << PAINT_ANNO(p));	else if (p->tcp_header()->th_flags & TH_SYN)	    finfo->_flow_over = 0;    }#if CLICK_USERLEVEL    // count packets    if (stats() && PAINT_ANNO(p) < 2) {	StatFlowInfo *sinfo = static_cast<StatFlowInfo *>(finfo);	sinfo->_packets[PAINT_ANNO(p)]++;    }#endif}voidAggregateIPFlows::reap_map(Map &table, uint32_t timeout, uint32_t done_timeout){    timeout = _active_sec - timeout;    done_timeout = _active_sec - done_timeout;    int frag_timeout = _active_sec - _fragment_timeout;    // free completed flows and emit fragments    for (Map::iterator iter = table.begin(); iter.live(); iter++) {	HostPairInfo *hpinfo = &iter.value();	Packet *head;	// fragments	while ((head = hpinfo->_fragment_head)	       && (head->timestamp_anno().sec() < frag_timeout		   || !IP_ISFRAG(good_ip_header(head))))	    emit_fragment_head(hpinfo);	// can't delete any flows if there are fragments	if (hpinfo->_fragment_head)	    continue;	// completed flows	FlowInfo **pprev = &hpinfo->_flows;	FlowInfo *f = *pprev;	while (f) {	    // circular comparison	    if (SEC_OLDER(f->_last_timestamp.sec(), (f->_flow_over == 3 ? done_timeout : timeout))) {		notify(f->_aggregate, AggregateListener::DELETE_AGG, 0);		*pprev = f->_next;		delete_flowinfo(iter.key(), f);	    } else		pprev = &f->_next;	    f = *pprev;	}	// XXX never free host pairs    }}voidAggregateIPFlows::reap()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -