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

📄 gridroutetable.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 3 页
字号:
/* * gridroutetable.{cc,hh} -- Grid local neighbor and route tables element * Douglas S. J. De Couto * * Copyright (c) 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 "timeutils.hh" /* includes <cmath> which may #undef NULL, so			   must become before <cstddef> */#include <click/confparse.hh>#include <click/error.hh>#include <clicknet/ether.h>#include <clicknet/ip.h>#include <click/standard/scheduleinfo.hh>#include <click/router.hh>#include <click/element.hh>#include <click/glue.hh>#include "gridroutetable.hh"#include "gridlogger.hh"CLICK_DECLS#define NEXT_HOP_ETH_FIXUP 0boolGridRouteTable::get_one_entry(const IPAddress &dest_ip, RouteEntry &entry) {  RTEntry *r = _rtes.findp(dest_ip);  if (r == 0)    return false;    entry = RouteEntry(dest_ip, r->loc_good, r->loc_err, r->loc,		     r->next_hop_eth, r->next_hop_ip, 		     0, // ignore interface number info		     r->seq_no(), r->num_hops());  return true;  }voidGridRouteTable::get_all_entries(Vector<RouteEntry> &vec){  for (RTIter iter = _rtes.begin(); iter; iter++) {    const RTEntry &rte = iter.value();    vec.push_back(RouteEntry(rte.dest_ip, rte.loc_good, rte.loc_err, rte.loc, 			     rte.next_hop_eth, rte.next_hop_ip, 0, // ignore interface info			     rte.seq_no(), rte.num_hops()));  }}GridRouteTable::GridRouteTable() :   GridGenericRouteTable(1, 1), _log(0), _dump_tick(0),  _seq_no(0), _fake_seq_no(0), _bcast_count(0),  _seq_delay(1),  _max_hops(3),   _expire_timer(expire_hook, this),  _hello_timer(hello_hook, this),  _metric_type(MetricEstTxCount),  _max_metric(0), _min_metric(0),  _est_type(EstBySigQual),  _frozen(false){}GridRouteTable::~GridRouteTable(){}void *GridRouteTable::cast(const char *n){  if (strcmp(n, "GridRouteTable") == 0)    return (GridRouteTable *) this;  else if (strcmp(n, "GridGenericRouteTable") == 0)    return (GridGenericRouteTable *) this;  else    return 0;}voidGridRouteTable::log_route_table (){  char str[80];  for (RTIter i = _rtes.begin(); i; i++) {    const RTEntry &f = i.value();    snprintf(str, sizeof(str), 	     "%s %s %s %d %c %u\n", 	     f.dest_ip.s().cc(),	     f.loc.s().cc(),	     f.next_hop_ip.s().cc(),	     f.num_hops(),	     (f.is_gateway ? 'y' : 'n'),	     f.seq_no());    _extended_logging_errh->message(str);  }  _extended_logging_errh->message("\n");}intGridRouteTable::configure(Vector<String> &conf, ErrorHandler *errh){  String chan("routelog");  String metric("est_tx_count");  int res = cp_va_parse(conf, this, errh,			cpInteger, "entry timeout (msec)", &_timeout,			cpInteger, "route broadcast period (msec)", &_period,			cpInteger, "route broadcast jitter (msec)", &_jitter,			cpEthernetAddress, "source Ethernet address", &_eth,			cpIPAddress, "source IP address", &_ip,			cpElement, "GridGatewayInfo element", &_gw_info,			cpElement, "LinkTracker element", &_link_tracker,			cpElement, "LinkStat element", &_link_stat,			cpKeywords,			"MAX_HOPS", cpInteger, "max hops", &_max_hops,			"LOGCHANNEL", cpString, "log channel name", &chan,			"METRIC", cpString, "route metric", &metric,			"LOG", cpElement, "GridLogger element", &_log,			cpEnd);  if (res < 0)    return res;  // convert msecs to jiffies  if (_timeout == 0)    _timeout = -1;  if (_timeout > 0) {    _timeout_jiffies = msec_to_jiff(_timeout);    if (_timeout_jiffies < 1)      return errh->error("timeout interval is too small");  }  else    click_chatter("%s: not timing out table entries", id().cc());  if (_period <= 0)    return errh->error("period must be greater than 0");  if (_jitter < 0)    return errh->error("period must be positive");  if (_jitter > _period)    return errh->error("jitter is bigger than period");  if (_max_hops < 0)    return errh->error("max hops must be greater than 0");  _extended_logging_errh = router()->chatter_channel(chan);  assert(_extended_logging_errh);  _metric_type = check_metric_type(metric);  if (_metric_type < 0)    return errh->error("Unknown metric type ``%s''", metric.cc());  return res;}intGridRouteTable::initialize(ErrorHandler *){  _hello_timer.initialize(this);  _hello_timer.schedule_after_ms(_period); // Send periodically  _expire_timer.initialize(this);  if (_timeout > 0)    _expire_timer.schedule_after_ms(EXPIRE_TIMER_PERIOD);  return 0;}boolGridRouteTable::current_gateway(RouteEntry &entry){  for (RTIter i = _rtes.begin(); i; i++) {    const RTEntry &f = i.value();    if (f.is_gateway) {      entry = RouteEntry(f.dest_ip, f.loc_good, f.loc_err, f.loc, 			 f.next_hop_eth, f.next_hop_ip, 0, // ignore interface info			 f.seq_no(), f.num_hops());      return true;      }  }  return false;}unsigned intGridRouteTable::qual_to_pct(int q){  /* smaller quality is better, so should be a higher pct when closer to min quality */  if (q > _max_metric)    return 0;  else if (q < _min_metric)     return 100;  int delta = _max_metric - _min_metric;  return (100 * (_max_metric - q)) / delta;}unsigned intGridRouteTable::sig_to_pct(int s){  /* large signal is better, so should be a higher pct when closer to max sig */  if (s > _max_metric)    return 100;  else if (s < _min_metric)     return 0;  int delta = _max_metric - _min_metric;  return (100 * (s - _min_metric)) / delta;}// #define h(x) click_chatter("XXXX %d", x);#define h(x)boolGridRouteTable::est_forward_delivery_rate(const IPAddress ip, double &rate){  switch (_est_type) {  case EstBySig:  case EstByQual:   case EstBySigQual: {    int sig = 0;    int qual = 0;    struct timeval last;    bool res = _link_tracker->get_stat(ip, sig, qual, last);    if (!res) {      h(1);      return false;    }    if (_est_type == EstByQual) {      return false;    }    else if (_est_type == EstBySig) {      return false;    }    else if (_est_type == EstBySigQual) {      h(2);#if 0      click_chatter("XXX %s", ip.s().cc());#endif      /*        * use jinyang's parameters, based on 1sec broadcast loss rates       * with 50-byte UDP packets.         *       * good = delivery rate > 80%.         *       * these parameters are chosen to correctly classify 85% of good       * links as good, while only classifying 2% of bad links as       * good.         */      res = _link_tracker->get_bcast_stat(ip, rate, last);      double z = 9.4519 + 0.0391 * sig + 0.5518 * qual;      double z2 = 1 / (1 + exp(z));      double thresh = 0.8;      bool link_good = z2 > thresh;      /* paper fuckedness: */      if (link_good)	rate = 1;      else	rate = 0.1;      return true;      h(3);      if (!link_good && !res) {	h(4);	return false;      }      else if (link_good && !res) {	h(5);	rate = 0.8;	return true;      }      else if (!link_good && res) {	h(6);	return true; /* rate was set in call to get_bcast_stat */      }      else /* link_good && res */ {	h(7);	if (rate < 0.8) {	  h(8);	  rate = 0.8;	}	return true;      }      h(9);    }    else {      h(10);      return false;    }  }  case EstByMeas: {    h(11);    struct timeval last;    bool res = _link_tracker->get_bcast_stat(ip, rate, last);    return res;    break;  }  default:    h(12);    return false;  }}boolGridRouteTable::est_reverse_delivery_rate(const IPAddress ip, double &rate){  switch (_est_type) {  case EstBySig:  case EstByQual:     h(101);    return false;    break;  case EstBySigQual: {    h(102);    RTEntry *r = _rtes.findp(ip);    if (r == 0 || r->num_hops() > 1) {      h(103);      return false;    }#if 0    struct timeval last;#if 0    LinkStat::stat_t *s = _link_stat->_stats.findp(r->next_hop_eth);#else    struct {      int qual;      int sig;      struct timeval when;    } *s = 0;#endif    if (s == 0) {      return false;      h(104);    }    double z = 9.4519 + 0.0391 * s->sig + 0.5518 * s->qual;    double z2 = 1 / (1 + exp(z));    double thresh = 0.8;    bool link_good = z2 > thresh;        /* paper fuckedness: */    if (link_good)      rate = 1;    else      rate = 0.1;    return true;        unsigned int window = 0;    unsigned int num_rx = 0;    unsigned int num_expected = 0;    bool res = false;_link_stat->get_bcast_stats(r->next_hop_eth, last, window, num_rx, num_expected);    if (res && num_expected > 1) {      h(105);      double num_rx_ = num_rx;      /* we assume all nodes have same hello period */      double num_expected_ = num_expected;      rate = (num_rx_ - 0.5) / num_expected_;    }    else {      h(107);      rate = 0;    }    if (!link_good && !res) {      h(108);      return false;    }    else if (link_good && !res) {      h(109);      rate = 0.8;      return true;    }    else if (!link_good && res) {      h(110);      return true; /* rate was set in call to get_bcast_stats */    }    else /* link_good && res */ {      h(111);      if (rate < 0.8) {	h(112);	rate = 0.8;      }      return true;    }#else    rate = 0;    return false;#endif  }  h(113);  case EstByMeas: {#if 0    struct timeval last;    RTEntry *r = _rtes.findp(ip);    if (r == 0 || r->num_hops() > 1)      return false;    unsigned int window = 0;    unsigned int num_rx = 0;    unsigned int num_expected = 0;    bool res = _link_stat->get_bcast_stats(r->next_hop_eth, last, window, num_rx, num_expected);    if (!res || num_expected <= 1)      return false;    double num_rx_ = num_rx;    double num_expected_ = num_expected;    if (num_rx > num_expected)      click_chatter("WARNING: est_reverse_delivery_rate: num_rx (%d) > num_expected (%d) for %s",		    num_rx, num_expected, r->next_hop_eth.s().cc());    rate = (num_rx_ - 0.5) / num_expected_;#endif    return true;    break;  }  default:    return false;  }}voidGridRouteTable::init_metric(RTEntry &r){  assert(r.num_hops() == 1);  switch (_metric_type) {  case MetricHopCount:    r.metric = r.num_hops();    r.metric_valid = true;    break;  case MetricMinDeliveryRate:  case MetricCumulativeDeliveryRate:    assert(0);    /* code to estimate our delivery rate to this 1-hop nbr goes here */    r.metric_valid = true;    break;  case MetricMinSigStrength:  case MetricMinSigQuality:   case MetricCumulativeQualPct:  case MetricCumulativeSigPct: {    int sig = 0;    int qual = 0;    struct timeval last;    bool res = _link_tracker->get_stat(r.dest_ip, sig, qual, last);    if (!res) {      click_chatter("GridRouteTable: no link sig/qual stats from 1-hop neighbor %s; not initializing metric\n",		    r.dest_ip.s().cc());      r.metric = _bad_metric;      r.metric_valid = false;      return;    }    struct timeval now;    gettimeofday(&now, 0);    now = now - last;    int delta_ms = 1000 * now.tv_sec + (now.tv_usec / 1000);    if (delta_ms > _timeout) {      click_chatter("GridRouteTable: link sig/qual stats from 1-hop neighbor %s are too old; not initializing metric\n",		    r.dest_ip.s().cc());      r.metric = _bad_metric;      r.metric_valid = false;      return;    }    if (_metric_type == MetricMinSigQuality)       r.metric = (unsigned int) qual;    else if (_metric_type == MetricMinSigStrength)      r.metric = (unsigned int) -sig; // deal in -dBm    else if (_metric_type == MetricCumulativeQualPct)       r.metric = qual_to_pct(qual);    else // _metric_type == MetricCumulativeSigPct      r.metric = sig_to_pct(sig);    r.metric_valid = true;  }  break;  case MetricEstTxCount: {#if 0    click_chatter("XXX");#endif    double fwd_rate = 0;    double rev_rate = 0;    bool res = est_forward_delivery_rate(r.next_hop_ip, fwd_rate);    bool res2 = est_reverse_delivery_rate(r.next_hop_ip, rev_rate);#if 0    char buf[255];    snprintf(buf, 255, "YYY %s %s -- res: %s, res2: %s, fwd: %f, rev: %f",	     r.dest_ip.s().cc(), r.next_hop_ip.s().cc(),	     res ? "true" : "false", res2 ? "true" : "false",	     fwd_rate, rev_rate);    click_chatter(buf);#endif    if (res && res2 && fwd_rate > 0 && rev_rate > 0) {      if (fwd_rate >= 1) {	click_chatter("init_metric ERROR: fwd rate %d is too high for %s",		      (int) (100 * fwd_rate), r.next_hop_ip.s().cc());	fwd_rate = 1;      }      if (rev_rate >= 1) {	click_chatter("init_metric ERROR: rev rate %d is too high for %s",		      (int) (100 * rev_rate), r.next_hop_ip.s().cc());	rev_rate = 1;      }      r.metric = (int) (100 / (fwd_rate * rev_rate));      if (r.metric < 100) 	click_chatter("init_metric WARNING: metric too small (%d) for %s",		      r.metric, r.next_hop_ip.s().cc());      r.metric_valid = true;      h(201);    }     else {      r.metric = _bad_metric;      r.metric_valid = false;      h(202);    }    break;  }  default:    assert(0);  }} void GridRouteTable::update_metric(RTEntry &r){  if (r.num_hops() == 0)    return; // is broken route ad  RTEntry *next_hop = _rtes.findp(r.next_hop_ip);  if (!next_hop) {    click_chatter("GridRouteTable: ERROR updating metric for %s; no information for next hop %s; invalidating metric",		  r.dest_ip.s().cc(), r.next_hop_ip.s().cc());    r.metric_valid = false;    return;  }

⌨️ 快捷键说明

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