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

📄 autoratefallback.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * autoratefallback.{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 <clicknet/wifi.h>#include <elements/wifi/availablerates.hh>#include "autoratefallback.hh"CLICK_DECLS#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))AutoRateFallback::AutoRateFallback()  : Element(2, 1),    _stepup(10),    _stepdown(1),    _offset(0),    _packet_size_threshold(0){  /* bleh */  static unsigned char bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };  _bcast = EtherAddress(bcast_addr);}AutoRateFallback::~AutoRateFallback(){}voidAutoRateFallback::notify_noutputs(int n){  set_noutputs(n <= 2 ? n : 1);}intAutoRateFallback::configure(Vector<String> &conf, ErrorHandler *errh){  _active = true;  _adaptive_stepup = true;  int ret = cp_va_parse(conf, this, errh,			cpKeywords, 			"OFFSET", cpUnsigned, "offset", &_offset,			"ADAPTIVE_STEPUP", cpBool, "offset", &_adaptive_stepup,			"STEPUP", cpInteger, "0-100", &_stepup,			"STEPDOWN", cpInteger, "0-100", &_stepdown,			"RT", cpElement, "availablerates", &_rtable,			"THRESHOLD", cpUnsigned, "xxx", &_packet_size_threshold,			"ACTIVE", cpBool, "xxx", &_active,			cpEnd);  return ret;}voidAutoRateFallback::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 *eh = (struct click_wifi_extra *) p_in->all_user_anno();  bool success = !(eh->flags & WIFI_EXTRA_TX_FAIL);  bool used_alt_rate = (eh->flags & WIFI_EXTRA_TX_USED_ALT_RATE);  int rate = eh->rate;  struct timeval now;  click_gettimeofday(&now);    if (dst.is_group()) {    /* don't record info for bcast packets */    return;  }  if (0 == rate) {    /* rate wasn't set */    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      */    return;  }  DstInfo *nfo = _neighbors.findp(dst);  if (!nfo) {    return;  }  if (nfo->_rates[nfo->_current_index] != rate) {    return;  }  if (used_alt_rate || !success) {    /* step down 1 or 2 rates */    int down = eh->retries / 2;    if (down > 0) {      down--;    }    int next_index = max(0, nfo->_current_index - down);    if (_debug) {      click_chatter("%{element} stepping down for %s from %d to %d\n",		    this,		    nfo->_eth.s().cc(),		    nfo->_rates[nfo->_current_index],		    nfo->_rates[next_index]);    }        if (nfo->_wentup && _adaptive_stepup) {      /* backoff the stepup */      nfo->_stepup *= 2;      nfo->_wentup = false;    } else {      nfo->_stepup = _stepup;    }    nfo->_successes = 0;    nfo->_current_index = next_index;    return;  }  if (nfo->_wentup) {    /* reset adaptive stepup on a success */    nfo->_stepup = _stepup;  }  nfo->_wentup = false;  if (eh->retries == 0) {    nfo->_successes++;  } else {    nfo->_successes = 0;  }  if (nfo->_successes > nfo->_stepup &&       nfo->_current_index != nfo->_rates.size() - 1) {    if (_debug) {      click_chatter("%{element} steping up for %s from %d to %d\n",		    this,		    nfo->_eth.s().cc(),		    nfo->_rates[nfo->_current_index],		    nfo->_rates[min(nfo->_rates.size() - 1, 				    nfo->_current_index + 1)]);    }    nfo->_current_index = min(nfo->_current_index + 1, nfo->_rates.size() - 1);    nfo->_successes = 0;    nfo->_wentup = true;  }  return;}voidAutoRateFallback::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 *eh = (struct click_wifi_extra *) p_in->all_user_anno();  eh->magic = WIFI_EXTRA_MAGIC;  if (dst.is_group()) {    Vector<int> rates = _rtable->lookup(_bcast);    if (rates.size()) {      eh->rate = rates[0];    } else {      eh->rate = 2;    }    click_chatter("set auto rate %d", eh->rate);    return;  }  DstInfo *nfo = _neighbors.findp(dst);  if (!nfo || !nfo->_rates.size()) {    _neighbors.insert(dst, DstInfo(dst));    nfo = _neighbors.findp(dst);    nfo->_rates = _rtable->lookup(dst);    nfo->_successes = 0;    nfo->_wentup = false;    nfo->_stepup = _stepup;    /* start at the highest rate */    nfo->_current_index = nfo->_rates.size() - 1;    if (_debug) {      click_chatter("%{element} initial rate for %s is %d\n",		    this,		    nfo->_eth.s().cc(),		    nfo->_rates[nfo->_current_index]);    }  }  int ndx = nfo->_current_index;  eh->rate = nfo->_rates[ndx];  eh->rate1 = (ndx - 1 >= 0) ? nfo->_rates[max(ndx - 1, 0)] : 0;  eh->rate2 = (ndx - 2 >= 0) ? nfo->_rates[max(ndx - 2, 0)] : 0;  eh->rate3 = (ndx - 3 >= 0) ? nfo->_rates[max(ndx - 3, 0)] : 0;  click_chatter("set auto rate %d", eh->rate);  eh->max_tries = 4;  eh->max_tries1 = (ndx - 1 >= 0) ? 2 : 0;  eh->max_tries2 = (ndx - 2 >= 0) ? 2 : 0;  eh->max_tries3 = (ndx - 3 >= 0) ? 2 : 0;  return;  }Packet *AutoRateFallback::pull(int port){  Packet *p = input(port).pull();  if (p && _active) {    assign_rate(p);  }  return p;}voidAutoRateFallback::push(int port, Packet *p_in){  if (!p_in) {    return;  }  if (_active) {    if (port != 0) {      process_feedback(p_in);    } else {      click_chatter("assigining rates");      assign_rate(p_in);    }  }  checked_output_push(port, p_in);}StringAutoRateFallback::print_rates() {    StringAccum sa;  for (NIter iter = _neighbors.begin(); iter; iter++) {    DstInfo nfo = iter.value();    sa << nfo._eth << " ";    sa << nfo._rates[nfo._current_index] << " ";    sa << nfo._successes << "\n";  }  return sa.take_string();}enum {H_DEBUG, H_STEPUP, H_STEPDOWN, H_THRESHOLD, H_RATES, H_RESET,       H_OFFSET, H_ACTIVE};static StringAutoRateFallback_read_param(Element *e, void *thunk){  AutoRateFallback *td = (AutoRateFallback *)e;  switch ((uintptr_t) thunk) {  case H_DEBUG:    return String(td->_debug) + "\n";  case H_STEPDOWN:    return String(td->_stepdown) + "\n";  case H_STEPUP:    return String(td->_stepup) + "\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 AutoRateFallback_write_param(const String &in_s, Element *e, void *vparam,		      ErrorHandler *errh){  AutoRateFallback *f = (AutoRateFallback *)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_STEPUP: {    unsigned m;    if (!cp_unsigned(s, &m))       return errh->error("stepup parameter must be unsigned");    f->_stepup = m;    break;  }  case H_STEPDOWN: {    unsigned m;    if (!cp_unsigned(s, &m))       return errh->error("stepdown parameter must be unsigned");    f->_stepdown = m;    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;}voidAutoRateFallback::add_handlers(){  add_default_handlers(true);  add_read_handler("debug", AutoRateFallback_read_param, (void *) H_DEBUG);  add_read_handler("rates", AutoRateFallback_read_param, (void *) H_RATES);  add_read_handler("threshold", AutoRateFallback_read_param, (void *) H_THRESHOLD);  add_read_handler("stepup", AutoRateFallback_read_param, (void *) H_STEPUP);  add_read_handler("stepdown", AutoRateFallback_read_param, (void *) H_STEPDOWN);  add_read_handler("offset", AutoRateFallback_read_param, (void *) H_OFFSET);  add_read_handler("active", AutoRateFallback_read_param, (void *) H_ACTIVE);  add_write_handler("debug", AutoRateFallback_write_param, (void *) H_DEBUG);  add_write_handler("threshold", AutoRateFallback_write_param, (void *) H_THRESHOLD);  add_write_handler("stepup", AutoRateFallback_write_param, (void *) H_STEPUP);  add_write_handler("stepdown", AutoRateFallback_write_param, (void *) H_STEPDOWN);  add_write_handler("reset", AutoRateFallback_write_param, (void *) H_RESET);  add_write_handler("offset", AutoRateFallback_write_param, (void *) H_OFFSET);  add_write_handler("active", AutoRateFallback_write_param, (void *) H_ACTIVE);}// generate Vector template instance#include <click/bighashmap.cc>#include <click/dequeue.cc>#if EXPLICIT_TEMPLATE_INSTANCEStemplate class HashMap<EtherAddress, AutoRateFallback::DstInfo>;template class DEQueue<AutoRateFallback::tx_result>;#endifCLICK_ENDDECLSEXPORT_ELEMENT(AutoRateFallback)

⌨️ 快捷键说明

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