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

📄 aggcounter.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * aggcounter.{cc,hh} -- count packets/bytes with given aggregate * Eddie Kohler after Greg Minshall * * Copyright (c) 2001 International Computer Science Institute * * 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 "aggcounter.hh"#include <click/handlercall.hh>#include <click/confparse.hh>#include <click/error.hh>#include <click/packet_anno.hh>#include <click/integers.hh>	// for first_bit_set#include <click/router.hh>CLICK_DECLSAggregateCounter::AggregateCounter()    : Element(1, 1), _root(0), _free(0), _call_nnz_h(0), _call_count_h(0){}AggregateCounter::~AggregateCounter(){}AggregateCounter::Node *AggregateCounter::new_node_block(){    assert(!_free);    int block_size = 1024;    Node *block = new Node[block_size];    if (!block)	return 0;    _blocks.push_back(block);    for (int i = 1; i < block_size - 1; i++)	block[i].child[0] = &block[i+1];    block[block_size - 1].child[0] = 0;    _free = &block[1];    return &block[0];}voidAggregateCounter::notify_ninputs(int n){    set_ninputs(n <= 1 ? 1 : 2);}voidAggregateCounter::notify_noutputs(int n){    set_noutputs(n <= 1 ? 1 : 2);}intAggregateCounter::configure(Vector<String> &conf, ErrorHandler *errh){    bool bytes = false;    bool ip_bytes = false;    bool packet_count = true;    bool extra_length = true;    uint32_t freeze_nnz, stop_nnz;    uint64_t freeze_count, stop_count;    String call_nnz, call_count;    freeze_nnz = stop_nnz = _call_nnz = (uint32_t)(-1);    freeze_count = stop_count = _call_count = (uint64_t)(-1);        if (cp_va_parse(conf, this, errh,		    cpKeywords,		    "BYTES", cpBool, "count bytes?", &bytes,		    "IP_BYTES", cpBool, "do not count link header bytes?", &ip_bytes,		    "MULTIPACKET", cpBool, "use packet count annotation?", &packet_count,		    "EXTRA_LENGTH", cpBool, "use extra length annotation?", &extra_length,		    "AGGREGATE_FREEZE", cpUnsigned, "freeze after N nonzero aggregates", &freeze_nnz,		    "COUNT_FREEZE", cpUnsigned64, "freeze after count reaches N", &freeze_count,		    "AGGREGATE_STOP", cpUnsigned, "stop router after N nonzero aggregates", &stop_nnz,		    "COUNT_STOP", cpUnsigned64, "stop router after count reaches N", &stop_count,		    "AGGREGATE_CALL", cpArgument, "call handler after N nonzero aggregates", &call_nnz,		    "COUNT_CALL", cpArgument, "call handler after count reaches N", &call_count,		    "BANNER", cpString, "output banner", &_output_banner,		    cpEnd) < 0)	return -1;        _bytes = bytes;    _ip_bytes = ip_bytes;    _use_packet_count = packet_count;    _use_extra_length = extra_length;    if ((freeze_nnz != (uint32_t)(-1)) + (stop_nnz != (uint32_t)(-1)) + ((bool)call_nnz) > 1)	return errh->error("'AGGREGATE_FREEZE', 'AGGREGATE_STOP', and 'AGGREGATE_CALL' are mutually exclusive");    else if (freeze_nnz != (uint32_t)(-1)) {	_call_nnz = freeze_nnz;	_call_nnz_h = new HandlerCall(id() + ".freeze true");    } else if (stop_nnz != (uint32_t)(-1)) {	_call_nnz = stop_nnz;	_call_nnz_h = new HandlerCall(id() + ".stop");    } else if (call_nnz) {	if (!cp_unsigned(cp_pop_spacevec(call_nnz), &_call_nnz))	    return errh->error("'AGGREGATE_CALL' first word should be unsigned (number of aggregates)");	_call_nnz_h = new HandlerCall(call_nnz);    }        if ((freeze_count != (uint64_t)(-1)) + (stop_count != (uint64_t)(-1)) + ((bool)call_count) > 1)	return errh->error("'COUNT_FREEZE', 'COUNT_STOP', and 'COUNT_CALL' are mutually exclusive");    else if (freeze_count != (uint64_t)(-1)) {	_call_count = freeze_count;	_call_count_h = new HandlerCall(id() + ".freeze true");    } else if (stop_count != (uint64_t)(-1)) {	_call_count = stop_count;	_call_count_h = new HandlerCall(id() + ".stop");    } else if (call_count) {	if (!cp_unsigned64(cp_pop_spacevec(call_count), &_call_count))	    return errh->error("'COUNT_CALL' first word should be unsigned (count)");	_call_count_h = new HandlerCall(call_count);    }        return 0;}intAggregateCounter::initialize(ErrorHandler *errh){    if (_call_nnz_h && _call_nnz_h->initialize_write(this, errh) < 0)	return -1;    if (_call_count_h && _call_count_h->initialize_write(this, errh) < 0)	return -1;    if (clear(errh) < 0)	return -1;        _frozen = false;    _active = true;    return 0;}voidAggregateCounter::cleanup(CleanupStage){    for (int i = 0; i < _blocks.size(); i++)	delete[] _blocks[i];    _blocks.clear();    delete _call_nnz_h;    delete _call_count_h;    _call_nnz_h = _call_count_h = 0;}AggregateCounter::Node *AggregateCounter::make_peer(uint32_t a, Node *n, bool frozen){    /*     * become a peer     * algo: create two nodes, the two peers.  leave orig node as     * the parent of the two new ones.     */    if (frozen)	return 0;        Node *down[2];    if (!(down[0] = new_node()))	return 0;    if (!(down[1] = new_node())) {	free_node(down[0]);	return 0;    }    // swivel is first bit 'a' and 'old->input' differ    int swivel = ffs_msb(a ^ n->aggregate);    // bitvalue is the value of that bit of 'a'    int bitvalue = (a >> (32 - swivel)) & 1;    // mask masks off all bits before swivel    uint32_t mask = (swivel == 1 ? 0 : (0xFFFFFFFFU << (33 - swivel)));    down[bitvalue]->aggregate = a;    down[bitvalue]->count = 0;    down[bitvalue]->child[0] = down[bitvalue]->child[1] = 0;    *down[1 - bitvalue] = *n;	/* copy orig node down one level */    n->aggregate = (down[0]->aggregate & mask);    if (down[0]->aggregate == n->aggregate) {	n->count = down[0]->count;	down[0]->count = 0;    } else	n->count = 0;    n->child[0] = down[0];	/* point to children */    n->child[1] = down[1];    return (n->aggregate == a ? n : down[bitvalue]);}AggregateCounter::Node *AggregateCounter::find_node(uint32_t a, bool frozen){    // straight outta tcpdpriv    Node *n = _root;    while (n) {	if (n->aggregate == a)	    return (n->count || !frozen ? n : 0);	if (!n->child[0])	    n = make_peer(a, n, frozen);	else {	    // swivel is the first bit in which the two children differ	    int swivel = ffs_msb(n->child[0]->aggregate ^ n->child[1]->aggregate);	    if (ffs_msb(a ^ n->aggregate) < swivel) // input differs earlier		n = make_peer(a, n, frozen);	    else if (a & (1 << (32 - swivel)))		n = n->child[1];	    else		n = n->child[0];	}    }    if (!frozen)	click_chatter("AggregateCounter: out of memory!");    return 0;}inline boolAggregateCounter::update(Packet *p, bool frozen){    if (!_active)	return false;        // AGGREGATE_ANNO is already in host byte order!    uint32_t agg = AGGREGATE_ANNO(p);    Node *n = find_node(agg, frozen);    if (!n)	return false;        uint32_t amount;    if (!_bytes)	amount = 1 + (_use_packet_count ? EXTRA_PACKETS_ANNO(p) : 0);    else {	amount = p->length() + (_use_extra_length ? EXTRA_LENGTH_ANNO(p) : 0);	if (_ip_bytes && p->network_header())	    amount -= p->network_header_offset();    }        // update _num_nonzero; possibly call handler    if (amount && !n->count) {	if (_num_nonzero >= _call_nnz) {	    _call_nnz = (uint32_t)(-1);	    _call_nnz_h->call_write();	    // handler may have changed our state; reupdate	    return update(p, frozen || _frozen);	}	_num_nonzero++;    }        n->count += amount;    _count += amount;    if (_count >= _call_count) {	_call_count = (uint64_t)(-1);	_call_count_h->call_write();    }    return true;}voidAggregateCounter::push(int port, Packet *p){    port = !update(p, _frozen || (port == 1));    output(noutputs() == 1 ? 0 : port).push(p);}Packet *AggregateCounter::pull(int port){    Packet *p = input(ninputs() == 1 ? 0 : port).pull();    if (p && _active)	update(p, _frozen || (port == 1));    return p;}

⌨️ 快捷键说明

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