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

📄 probetxrate.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * probetxrate.{cc,hh} -- sets wifi txrate annotation on a packet * John Bicket * * Copyright (c) 2003 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 <click/confparse.hh>#include <click/error.hh>#include <click/glue.hh>#include <click/packet_anno.hh>#include <click/straccum.hh>#include <clicknet/ether.h>#include "probetxrate.hh"#include <elements/wifi/availablerates.hh>CLICK_DECLS#define PROBE_MAX_RETRIES 6ProbeTXRate::ProbeTXRate()  : Element(2, 1),    _offset(0),    _packet_size_threshold(0),    _rate_window_ms(0),    _rtable(0){  static unsigned char bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };  _bcast = EtherAddress(bcast_addr);}ProbeTXRate::~ProbeTXRate(){}voidProbeTXRate::notify_noutputs(int n){  set_noutputs(n <= 2 ? n : 1);}intProbeTXRate::configure(Vector<String> &conf, ErrorHandler *errh){  _debug = false;  _active = true;  _original_retries = 4;  _min_sample = 20;  int ret = cp_va_parse(conf, this, errh,			cpKeywords, 			"OFFSET", cpUnsigned, "offset", &_offset,			"WINDOW", cpUnsigned, "window", &_rate_window_ms,			"THRESHOLD", cpUnsigned, "threshold", &_packet_size_threshold,			"DEBUG", cpBool, "debug", &_debug,			"RT", cpElement, "availablerates", &_rtable,			"ACTIVE", cpBool, "xxx", &_active,			cpEnd);  if (ret < 0) {    return ret;  }  if (_rate_window_ms <= 0)     return errh->error("WINDOW must be > 0");  if (!_rtable || _rtable->cast("AvailableRates") == 0)     return errh->error("AvailableRates element is not provided or not a AvailableRates");  _rate_window = Timestamp::make_msec(_rate_window_ms);  return ret;}voidProbeTXRate::assign_rate(Packet *p_in) {  if (!p_in) {    click_chatter("%{element} ah, !p_in\n",		  this);    return;  }  uint8_t *dst_ptr = (uint8_t *) p_in->data() + _offset;  EtherAddress dst = EtherAddress(dst_ptr);  struct click_wifi_extra *ceh = (struct click_wifi_extra *) p_in->all_user_anno();  if (dst.is_group() || !dst) {    Vector<int> rates = _rtable->lookup(_bcast);    if (rates.size()) {      ceh->rate = rates[0];    } else {      ceh->rate = 2;    }    return;  }  DstInfo *nfo = _neighbors.findp(dst);  if (!nfo || !nfo->_rates.size()) {    _neighbors.insert(dst, DstInfo(dst, _rtable->lookup(dst)));    nfo = _neighbors.findp(dst);  }  nfo->trim(Timestamp::now() - _rate_window);  //nfo->check();  int best_ndx = nfo->best_rate_ndx();  if (nfo->_count++ % 10) {    // pick the best bit-rate    ceh->rate = nfo->_rates[best_ndx];    ceh->max_tries = 4;  } else {    //pick a random rate.    Vector<int> possible = nfo->pick_rate();    if (possible.size()) {      ceh->rate = possible[random() % possible.size()];      ceh->max_tries = 2;    } else {      // no rates to sample from      ceh->rate = nfo->_rates[best_ndx];      ceh->max_tries = 4;    }  }  ceh->rate1 = nfo->_rates[best_ndx];  ceh->max_tries1 = 2;  ceh->rate2 = 0;  ceh->max_tries2 = 0;  ceh->rate3 = 0;  ceh->max_tries3 = 0;  return;}voidProbeTXRate::process_feedback(Packet *p_in) {  if (!p_in) {    return;  }  uint8_t *dst_ptr = (uint8_t *) p_in->data() + _offset;  EtherAddress dst = EtherAddress(dst_ptr);  struct click_wifi_extra *ceh = (struct click_wifi_extra *) p_in->all_user_anno();  bool success = !(ceh->flags & WIFI_EXTRA_TX_FAIL);  int retries = ceh->retries;  Timestamp now = Timestamp::now();  if (dst == _bcast) {    /* don't record info for bcast packets */    if (_debug) {      click_chatter("%{element}: discarding bcast %s\n",		    this,		    dst.s().cc());    }    return;  }  if (0 == ceh->rate) {    /* rate wasn't set */    if (_debug) {          click_chatter("%{element} no rate set for %s\n",			this,			dst.s().cc());    }    return;  }    if (!success && p_in->length() < _packet_size_threshold) {    /*      * don't deal with short packets,      * since they can skew what rate     * we should be at      */    if (_debug) {          click_chatter("%{element} short success for %s\n",			this,			dst.s().cc());    }    return;  }  DstInfo *nfo = _neighbors.findp(dst);  if (!nfo) {    if (_debug) {          click_chatter("%{element} no info for %s\n",			this,			dst.s().cc());    }    return;  }  if (!success && _debug) {    click_chatter("%{element} packet failed %s retries %d rate %d alt %d\n",		  this,		  dst.s().cc(),		  retries,		  ceh->rate,		  ceh->rate1);  }  int tries = retries+1;  bool s = (tries <= ceh->max_tries);  int time = calc_usecs_wifi_packet(1500, ceh->rate, 				    MIN(tries,ceh->max_tries)-1);  if (_debug) {    click_chatter("%{element}::%s() rate %d tries %d time %d\n",		  this, __func__,		  ceh->rate,		  tries, time);  }  nfo->add_result(now, ceh->rate, MIN(tries,ceh->max_tries), 		  s, time);  //nfo->check();  return ;}Packet *ProbeTXRate::pull(int port){  Packet *p = input(port).pull();  if (p && _active) {    assign_rate(p);  }  return p;}voidProbeTXRate::push(int port, Packet *p_in){  if (!p_in) {    return;  }  if (_active) {    if (port != 0) {      process_feedback(p_in);    } else {      assign_rate(p_in);    }  }  checked_output_push(port, p_in);}StringProbeTXRate::print_rates() {  StringAccum sa;  for (NIter iter = _neighbors.begin(); iter; iter++) {    DstInfo nfo = iter.value();    sa << nfo._eth << "\n";    for (int x = 0; x < nfo._rates.size(); x++) {	sa << " " << nfo._rates[x];	sa << " success " << nfo._total_success[x];	sa << " fail " << nfo._total_fail[x];	sa << " perfect_usecs " << nfo._perfect_time[x];	sa << " total_usecs " << nfo._total_time[x];	sa << " average_usecs " << nfo.average(x);	sa << " average_tries ";	if (nfo._packets[x]) {	  Timestamp average_tries = Timestamp::make_msec(nfo._total_tries[x] * 1000 / nfo._packets[x]);	  sa << average_tries;	} else {	  sa << "0";	}	sa << "\n";    }  }  return sa.take_string();}enum {H_DEBUG,       H_RATES,       H_THRESHOLD,       H_RESET,       H_OFFSET,      H_ACTIVE,      };static StringProbeTXRate_read_param(Element *e, void *thunk){  ProbeTXRate *td = (ProbeTXRate *)e;  switch ((uintptr_t) thunk) {  case H_DEBUG:     return String(td->_debug) + "\n";  case H_THRESHOLD: return String(td->_packet_size_threshold) + "\n";  case H_OFFSET:    return String(td->_offset) + "\n";  case H_RATES:     return td->print_rates();  case H_ACTIVE:    return String(td->_active) + "\n";  default:    return String();  }}static int ProbeTXRate_write_param(const String &in_s, Element *e, void *vparam,		      ErrorHandler *errh){  ProbeTXRate *f = (ProbeTXRate *)e;  String s = cp_uncomment(in_s);  switch((int)vparam) {  case H_DEBUG: {    bool debug;    if (!cp_bool(s, &debug))       return errh->error("debug parameter must be boolean");    f->_debug = debug;    break;  }  case H_THRESHOLD: {    unsigned m;    if (!cp_unsigned(s, &m))       return errh->error("threshold parameter must be unsigned");    f->_packet_size_threshold = m;    break;  }  case H_OFFSET: {    unsigned m;    if (!cp_unsigned(s, &m))       return errh->error("offset parameter must be unsigned");    f->_offset = m;    break;  }  case H_RESET:    f->_neighbors.clear();    break; case H_ACTIVE: {    bool active;    if (!cp_bool(s, &active))       return errh->error("active must be boolean");    f->_active = active;    break;  }  }  return 0;}voidProbeTXRate::add_handlers(){  add_default_handlers(true);  add_read_handler("debug", ProbeTXRate_read_param, (void *) H_DEBUG);  add_read_handler("rates", ProbeTXRate_read_param, (void *) H_RATES);  add_read_handler("threshold", ProbeTXRate_read_param, (void *) H_THRESHOLD);  add_read_handler("offset", ProbeTXRate_read_param, (void *) H_OFFSET);  add_read_handler("active", ProbeTXRate_read_param, (void *) H_ACTIVE);  add_write_handler("debug", ProbeTXRate_write_param, (void *) H_DEBUG);  add_write_handler("threshold", ProbeTXRate_write_param, (void *) H_THRESHOLD);  add_write_handler("offset", ProbeTXRate_write_param, (void *) H_OFFSET);  add_write_handler("reset", ProbeTXRate_write_param, (void *) H_RESET);  add_write_handler("active", ProbeTXRate_write_param, (void *) H_ACTIVE);  }// generate Vector template instance#include <click/bighashmap.cc>#include <click/dequeue.cc>#if EXPLICIT_TEMPLATE_INSTANCEStemplate class HashMap<EtherAddress, ProbeTXRate::DstInfo>;template class DEQueue<ProbeTXRate::tx_result>;#endifCLICK_ENDDECLSELEMENT_REQUIRES(bitrate)EXPORT_ELEMENT(ProbeTXRate)

⌨️ 快捷键说明

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