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

📄 aggregateipflows.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 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 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;}static inline uint32_thashcode(const AggregateIPFlows::HostPair &a){    return (a.a << 12) + a.b + ((a.a >> 20) & 0x1F);}static inline uint32_tflip_ports(uint32_t ports){    return ((ports >> 16) & 0xFFFF) | (ports << 16);}// actual AggregateIPFlows operationsAggregateIPFlows::AggregateIPFlows()    : Element(1, 1), _traceinfo_file(0), _packet_source(0), _filepos_h(0){}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);}voidAggregateIPFlows::notify_noutputs(int n){    set_noutputs(n <= 1 ? 1 : 2);}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_parse(conf, this, errh,		    cpKeywords,		    "TCP_TIMEOUT", cpSeconds, "timeout for active TCP connections", &_tcp_timeout,		    "TCP_DONE_TIMEOUT", cpSeconds, "timeout for completed TCP connections", &_tcp_done_timeout,		    "UDP_TIMEOUT", cpSeconds, "timeout for UDP connections", &_udp_timeout,		    "FRAGMENT_TIMEOUT", cpSeconds, "timeout for fragment collection", &_fragment_timeout,		    "REAP", cpSeconds, "garbage collection interval", &_gc_interval,		    "ICMP", cpBool, "handle ICMP errors?", &handle_icmp_errors,		    "TRACEINFO", cpFilename, "filename for connection info file", &_traceinfo_filename,		    "SOURCE", cpElement, "packet source element", &_packet_source,		    cpConfirmKeywords,		    "FRAGMENTS", cpBool, "handle fragmented packets?", &gave_fragments, &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 (_traceinfo_filename == "-")	_traceinfo_file = stdout;    else if (_traceinfo_filename && !(_traceinfo_file = fopen(_traceinfo_filename.cc(), "w")))	return errh->error("%s: %s", _traceinfo_filename.cc(), 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.cc());	    (void) HandlerCall::reset_read(_filepos_h, _packet_source, "packet_filepos");	}	fprintf(_traceinfo_file, ">\n");    }    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 (_traceinfo_file && _traceinfo_file != stdout) {	fprintf(_traceinfo_file, "</trace>\n");	fclose(_traceinfo_file);    }    delete _filepos_h;}inline voidAggregateIPFlows::delete_flowinfo(const HostPair &hp, FlowInfo *finfo, bool really_delete){    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.s().cc(), sport, dst.s().cc(), 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	if (really_delete)	    delete finfo;}voidAggregateIPFlows::clean_map(Map &table){    // free completed flows and emit fragments    for (Map::iterator iter = table.begin(); iter; 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);	}    }}voidAggregateIPFlows::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_unsigned(_filepos_h->call_read().trim_space(), &sinfo->_filepos);}inline voidAggregateIPFlows::packet_emit_hook(const Packet *p, const click_ip *iph, FlowInfo *finfo){    // 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;    }    // count packets    if (stats() && PAINT_ANNO(p) < 2) {	StatFlowInfo *sinfo = static_cast<StatFlowInfo *>(finfo);	sinfo->_packets[PAINT_ANNO(p)]++;    }}voidAggregateIPFlows::assign_aggregate(Map &table, HostPairInfo *hpinfo, int emit_before_sec){    Packet *first = hpinfo->_fragment_head;    uint16_t want_ip_id = good_ip_header(first)->ip_id;    // find FlowInfo    FlowInfo *finfo = 0;    if (AGGREGATE_ANNO(first)) {	for (finfo = hpinfo->_flows; finfo && finfo->_aggregate != AGGREGATE_ANNO(first); finfo = finfo->_next)	    /* nada */;    } else {	for (Packet *p = first; !finfo && p; p = p->next()) {	    const click_ip *iph = good_ip_header(p);	    if (iph->ip_id == want_ip_id) {		if (IP_FIRSTFRAG(iph)) {		    uint32_t ports = *(reinterpret_cast<const uint32_t *>(reinterpret_cast<const uint8_t *>(iph) + (iph->ip_hl << 2)));		    if (PAINT_ANNO(p) & 1)			ports = flip_ports(ports);		    finfo = find_flow_info(table, hpinfo, ports, PAINT_ANNO(p) & 1, p);		}	    }	}    }    // if no FlowInfo found, delete packet    if (!finfo) {	hpinfo->_fragment_head = first->next();	first->kill();	return;    }    // emit packets at the beginning of the list that have the same IP ID    const click_ip *iph;    while (first && (iph = good_ip_header(first)) && iph->ip_id == want_ip_id	   && (SEC_OLDER(first->timestamp_anno().sec(), emit_before_sec)	       || !IP_ISFRAG(iph))) {	Packet *p = first;	hpinfo->_fragment_head = first = p->next();	p->set_next(0);	bool was_fragment = IP_ISFRAG(iph);	SET_AGGREGATE_ANNO(p, finfo->aggregate());	// actually emit packet	if (finfo->reverse())	    SET_PAINT_ANNO(p, PAINT_ANNO(p) ^ 1);	finfo->_last_timestamp = p->timestamp_anno();	packet_emit_hook(p, iph, finfo);	

⌨️ 快捷键说明

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