📄 regionpep.cc
字号:
/* * regionpep.{cc,hh} -- Region-based Grid Position Estimation Protocol * Douglas S. J. De Couto. from pep.{cc,hh} by Robert Morris. * * 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 "regionpep.hh"#include <click/confparse.hh>#include <click/error.hh>#include "grid.hh"CLICK_DECLSEstimateRouterRegion::EstimateRouterRegion() : _timer(this){ _fixed = false; _seq = 1; _debug = false;}EstimateRouterRegion::~EstimateRouterRegion(){}void *EstimateRouterRegion::cast(const char *name){ if(strcmp(name, "GridLocationInfo") == 0) return(this); return(GridLocationInfo::cast(name));}intEstimateRouterRegion::configure(Vector<String> &conf, ErrorHandler *errh){ int lat_int = 0, lon_int = 0; bool fixed = false; int res = cp_va_kparse(conf, this, errh, "IP", cpkP+cpkM, cpIPAddress, &_my_ip, "FIXED", cpkP, cpBool, &fixed, "LATITUDE", cpkP, cpReal10, 5, &lat_int, "LONGITUDE", cpkP, cpReal10, 5, &lon_int, cpEnd); if(res < 0) return(res); if(fixed){ float lat = ((float) lat_int) / 100000.0f; float lon = ((float) lon_int) / 100000.0f; if (lat > 90 || lat < -90) return errh->error("%s: latitude must be between +/- 90 degrees", name().c_str()); if (lon > 180 || lon < -180) return errh->error("%s: longitude must be between +/- 180 degrees", name().c_str()); _lat = lat; _lon = lon; _fixed = true; } return(0);}intEstimateRouterRegion::initialize(ErrorHandler *){ _timer.initialize(this); _timer.schedule_after_msec(pep_update * 1000); return 0;}voidEstimateRouterRegion::run_timer(Timer *){ purge_old(); output(0).push(make_PEP()); _timer.schedule_after_msec(click_random() % (pep_update * 1000 * 2));}voidEstimateRouterRegion::purge_old(){ Timestamp tv = Timestamp::now(); int i = 0; int j; for(j = 0; j < _entries.size(); j++){ if(tv.sec() - _entries[j]._when.sec() <= pep_purge){ _entries[i++] = _entries[j]; } else { if(_debug) click_chatter("EstimateRouterRegion %s %s: purging old entry for %s (%d %d %d)", name().c_str(), _my_ip.unparse().c_str(), IPAddress(_entries[j]._fix.fix_id).unparse().c_str(), (int) _entries[j]._when.sec(), (int) tv.sec(), pep_purge); } } static Entry dud; _entries.resize(i, dud);}voidEstimateRouterRegion::sort_entries(){ int n = _entries.size(); int i, j; for(i = 0; i < n; i++){ int h = _entries[i]._fix.fix_hops; for(j = i + 1; j < n; j++){ if(_entries[j]._fix.fix_hops < h){ Entry tmp = _entries[i]; _entries[i] = _entries[j]; _entries[j] = tmp; } } }}// Are we allowed to send a particular update?boolEstimateRouterRegion::sendable(Entry e){ Timestamp tv = Timestamp::now(); if(e._when.sec() + pep_stale > tv.sec() && e._fix.fix_hops < pep_max_hops){ return(true); } return(false);}voidEstimateRouterRegion::externalize(pep_rgn_fix *fp){ fp->fix_seq = htonl(fp->fix_seq); fp->fix_hops = htonl(fp->fix_hops);}voidEstimateRouterRegion::internalize(pep_rgn_fix *fp){ fp->fix_seq = ntohl(fp->fix_seq); fp->fix_hops = ntohl(fp->fix_hops);}Packet *EstimateRouterRegion::make_PEP(){ WritablePacket *p = Packet::make(sizeof(pep_rgn_proto)); memset(p->data(), 0, p->length()); pep_rgn_proto *pp = (pep_rgn_proto *) p->data(); pp->id = _my_ip.addr(); int nf = 0; if(_fixed){ pep_rgn_fix *f = pp->fixes + nf; nf++; f->fix_id = _my_ip.addr(); f->fix_seq = htonl(_seq++); f->fix_loc = grid_location(_lat, _lon); f->fix_dim = grid_location(0, 0); f->fix_hops = htonl(0); } else if (_entries.size() > 0) { // always include the best estimate of our region pep_rgn_fix *f = pp->fixes + nf; nf++; f->fix_id = _my_ip.addr(); f->fix_seq = htonl(_seq++); RectRegion rgn = build_region(); f->fix_loc = grid_location(rgn.y(), rgn.x()); f->fix_dim = grid_location(rgn.h(), rgn.w()); f->fix_hops = htonl(0); } sort_entries(); int i; for(i = 0; i < _entries.size() && nf < pep_proto_fixes; i++){ if(sendable(_entries[i])){ pp->fixes[nf] = _entries[i]._fix; externalize(&(pp->fixes[nf])); nf++; } } pp->n_fixes = htonl(nf); return p;}intEstimateRouterRegion::findEntry(unsigned id, bool create){ int i; for(i = 0; i < _entries.size(); i++) if(_entries[i]._fix.fix_id == id) return(i); if (create) { if (_debug) click_chatter("EstimateRouterRegion %s %s: new entry for %s", this->name().c_str(), _my_ip.unparse().c_str(), IPAddress(id).unparse().c_str()); i = _entries.size(); static Entry e; e._fix.fix_id = id; e._fix.fix_hops = -1; e._fix.fix_seq = -1; _entries.push_back(e); assert(_entries.size() == i+1 && _entries[i]._fix.fix_id == id); return(i); } else { return(-1); }}Packet *EstimateRouterRegion::simple_action(Packet *p){ int nf; pep_rgn_proto *pp; Timestamp tv = Timestamp::now(); if(p->length() != sizeof(pep_rgn_proto)) { click_chatter("EstimateRouterRegion: bad size packet (%d bytes)", p->length()); goto out; } pp = (pep_rgn_proto *) p->data(); nf = ntohl(pp->n_fixes); if(nf < 0 || (const u_char*)&pp->fixes[nf] > p->data()+p->length()){ click_chatter("EstimateRouterRegion: bad n_fixes %d", nf); goto out; } int i; for(i = 0; i < nf && i < pep_proto_fixes; i++){ pep_rgn_fix f = pp->fixes[i]; internalize(&f); if(f.fix_id == _my_ip.addr()) continue; int j = findEntry(f.fix_id, true); if(j < 0) continue; int os = _entries[j]._fix.fix_seq; int oh = _entries[j]._fix.fix_hops; if(f.fix_seq > os || (f.fix_seq == os && (f.fix_hops+1) < oh)){ _entries[j]._fix = f; _entries[j]._fix.fix_hops++; _entries[j]._when = tv; if(_debug && f.fix_hops != oh) click_chatter("EstimateRouterRegion %s %s: updating %s, seq %d -> %d, hops %d -> %d, my pos %s", name().c_str(), _my_ip.unparse().c_str(), IPAddress(f.fix_id).unparse().c_str(), os, f.fix_seq, oh, f.fix_hops, get_current_location().s().c_str()); } } out: p->kill(); return(0);}doubleEstimateRouterRegion::radio_range(grid_location) // XXX degrees lat covered by range{ return 0.002; }RectRegionEstimateRouterRegion::build_region(){ pep_rgn_fix f = _entries[0]._fix; RectRegion rgn(f.fix_loc.lon(), f.fix_loc.lat(), f.fix_dim.lon(), f.fix_dim.lat()); rgn = rgn.expand(f.fix_hops * radio_range(f.fix_loc)); int num_skips = 0; for (int i = 1; i < _entries.size(); i++) { f = _entries[i]._fix; RectRegion rgn2(f.fix_loc.lon(), f.fix_loc.lat(), f.fix_dim.lon(), f.fix_dim.lat()); rgn2 = rgn2.expand(f.fix_hops * radio_range(f.fix_loc)); RectRegion new_rgn = rgn2.intersect(rgn); if (new_rgn.empty()) { click_chatter("EstimateRouterRegion %s: skipping region which would result in empty intersection (%d)", name().c_str(), ++num_skips); continue; } rgn = new_rgn; } return rgn;}grid_locationEstimateRouterRegion::get_current_location(){ if(_fixed) return(grid_location(_lat, _lon)); if(_entries.size() < 1) return(grid_location(0.0, 0.0)); RectRegion rgn = build_region(); return grid_location(rgn.center_y(), rgn.center_x());}static Stringpep_read_handler(Element *f, void *){ EstimateRouterRegion *l = (EstimateRouterRegion *) f; return(l->s());}StringEstimateRouterRegion::s(){ String s; int i, n; Timestamp now = Timestamp::now(); if(_fixed){ s = _my_ip.unparse() + " " + grid_location(_lat, _lon).s() + "\n"; } else { s = _my_ip.unparse() + "\n"; } s += get_current_location().s() + "\n"; n = _entries.size(); for(i = 0; i < n; i++){ pep_rgn_fix f = _entries[i]._fix; char buf[512]; snprintf(buf, sizeof(buf), "%s seq=%d %s hops=%d age=%d\n", IPAddress(f.fix_id).unparse().c_str(), f.fix_seq, f.fix_loc.s().c_str(), f.fix_hops, (int)(now.sec() - _entries[i]._when.sec())); s += buf; } return s;}voidEstimateRouterRegion::add_handlers(){ add_read_handler("status", pep_read_handler, (void *) 0);}CLICK_ENDDECLSELEMENT_REQUIRES(GridLocationInfo Amoeba RectRegion)EXPORT_ELEMENT(EstimateRouterRegion)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -