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

📄 counter.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * counter.{cc,hh} -- element counts packets, measures packet rate * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * * 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 "counter.hh"#include <click/error.hh>#include <click/confparse.hh>#include <click/handlercall.hh>CLICK_DECLS#ifdef HAVE_INT64_TYPES# define PARSECMD cp_unsigned64#else# define PARSECMD cp_unsigned#endifCounter::Counter()  : Element(1, 1), _count_trigger_h(0), _byte_trigger_h(0){}Counter::~Counter(){  delete _count_trigger_h;  delete _byte_trigger_h;}voidCounter::reset(){  _count = _byte_count = 0;  _rate.initialize();  _count_triggered = _byte_triggered = false;}intCounter::configure(Vector<String> &conf, ErrorHandler *errh){  String count_call, byte_count_call;  if (cp_va_parse(conf, this, errh,		  cpKeywords,		  "COUNT_CALL", cpArgument, "handler to call after a count", &count_call,		  "BYTE_COUNT_CALL", cpArgument, "handler to call after a byte count", &byte_count_call,		  cpEnd) < 0)    return -1;  if (count_call) {    if (!PARSECMD(cp_pop_spacevec(count_call), &_count_trigger))      return errh->error("`COUNT_CALL' first word should be unsigned (count)");    _count_trigger_h = new HandlerCall(count_call);  } else    _count_trigger = (counter_t)(-1);  if (byte_count_call) {    if (!PARSECMD(cp_pop_spacevec(byte_count_call), &_byte_trigger))      return errh->error("`BYTE_COUNT_CALL' first word should be unsigned (count)");    _byte_trigger_h = new HandlerCall(byte_count_call);  } else    _byte_trigger = (counter_t)(-1);  return 0;}intCounter::initialize(ErrorHandler *errh){  if (_count_trigger_h && _count_trigger_h->initialize_write(this, errh) < 0)    return -1;  if (_byte_trigger_h && _byte_trigger_h->initialize_write(this, errh) < 0)    return -1;  reset();  return 0;}Packet *Counter::simple_action(Packet *p){  _count++;  _byte_count += p->length();  _rate.update(1);  if (_count == _count_trigger && !_count_triggered) {    _count_triggered = true;    if (_count_trigger_h)      (void) _count_trigger_h->call_write();  }  if (_byte_count >= _byte_trigger && !_byte_triggered) {    _byte_triggered = true;    if (_byte_trigger_h)      (void) _byte_trigger_h->call_write();  }    return p;}enum { H_COUNT, H_BYTE_COUNT, H_RATE, H_RESET,       H_COUNT_CALL, H_BYTE_COUNT_CALL };StringCounter::read_handler(Element *e, void *thunk){  Counter *c = (Counter *)e;  switch ((intptr_t)thunk) {   case H_COUNT:    return String(c->_count) + "\n";   case H_BYTE_COUNT:    return String(c->_byte_count) + "\n";   case H_RATE:    c->_rate.update_time();	// drop rate after zero period    return c->_rate.unparse() + "\n";   default:    return "<error>\n";  }}intCounter::write_handler(const String &in_str, Element *e, void *thunk, ErrorHandler *errh){  Counter *c = (Counter *)e;  String str = cp_uncomment(in_str);  switch ((intptr_t)thunk) {   case H_COUNT_CALL:    if (!PARSECMD(cp_pop_spacevec(str), &c->_count_trigger))      return errh->error("`count_call' first word should be unsigned (count)");    if (HandlerCall::reset_write(c->_count_trigger_h, str, c, errh) < 0)      return -1;    c->_count_triggered = false;    return 0;   case H_BYTE_COUNT_CALL:    if (!PARSECMD(cp_pop_spacevec(str), &c->_byte_trigger))      return errh->error("`byte_count_call' first word should be unsigned (count)");    if (HandlerCall::reset_write(c->_byte_trigger_h, str, c, errh) < 0)      return -1;    c->_byte_triggered = false;    return 0;   case H_RESET:    c->reset();    return 0;   default:    return errh->error("<internal>");  }}voidCounter::add_handlers(){  add_read_handler("count", read_handler, (void *)H_COUNT);  add_read_handler("byte_count", read_handler, (void *)H_BYTE_COUNT);  add_read_handler("rate", read_handler, (void *)H_RATE);  add_write_handler("reset", write_handler, (void *)H_RESET);  add_write_handler("reset_counts", write_handler, (void *)H_RESET);  add_write_handler("count_call", write_handler, (void *)H_COUNT_CALL);  add_write_handler("byte_count_call", write_handler, (void *)H_BYTE_COUNT_CALL);}intCounter::llrpc(unsigned command, void *data){  if (command == CLICK_LLRPC_GET_RATE) {    uint32_t *val = reinterpret_cast<uint32_t *>(data);    if (*val != 0)      return -EINVAL;    _rate.update_time();	// drop rate after zero period    *val = _rate.rate();    return 0;  } else if (command == CLICK_LLRPC_GET_COUNT) {    uint32_t *val = reinterpret_cast<uint32_t *>(data);    if (*val != 0 && *val != 1)      return -EINVAL;    *val = (*val == 0 ? _count : _byte_count);    return 0;      } else if (command == CLICK_LLRPC_GET_COUNTS) {    click_llrpc_counts_st *user_cs = (click_llrpc_counts_st *)data;    click_llrpc_counts_st cs;    if (CLICK_LLRPC_GET_DATA(&cs, data, sizeof(cs.n) + sizeof(cs.keys)) < 0	|| cs.n >= CLICK_LLRPC_COUNTS_SIZE)      return -EINVAL;    for (unsigned i = 0; i < cs.n; i++) {      if (cs.keys[i] == 0)	cs.values[i] = _count;      else if (cs.keys[i] == 1)	cs.values[i] = _byte_count;      else	return -EINVAL;    }    return CLICK_LLRPC_PUT_DATA(&user_cs->values, &cs.values, sizeof(cs.values));      } else    return Element::llrpc(command, data);}CLICK_ENDDECLSEXPORT_ELEMENT(Counter)

⌨️ 快捷键说明

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