📄 pep.cc
字号:
/* * pep.{cc,hh} -- Grid Position Estimation Protocol * 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 "pep.hh"#include "amoeba.hh"#include <click/confparse.hh>#include <click/error.hh>#include "grid.hh"#include <math.h>CLICK_DECLSPEP::PEP() : _timer(this){ add_input(); add_output(); _fixed = 0; _seq = 1; _debug = false;}PEP::~PEP(){}void *PEP::cast(const char *name){ if(strcmp(name, "GridLocationInfo") == 0) return(this); return(GridLocationInfo::cast(name));}intPEP::configure(Vector<String> &conf, ErrorHandler *errh){ int lat_int = 0, lon_int = 0; bool fixed = false; int res = cp_va_parse(conf, this, errh, cpIPAddress, "source IP address", &_my_ip, cpOptional, cpBool, "fixed?", &fixed, cpReal10, "latitude (decimal degrees)", 5, &lat_int, cpReal10, "longitude (decimal degrees)", 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", id().cc()); if (lon > 180 || lon < -180) return errh->error("%s: longitude must be between +/- 180 degrees", id().cc()); _lat = lat; _lon = lon; _fixed = true; } return(0);}intPEP::initialize(ErrorHandler *){ _timer.initialize(this); _timer.schedule_after_ms(pep_update * 1000); return 0;}voidPEP::run_timer(){ purge_old(); output(0).push(make_PEP()); _timer.schedule_after_ms(random() % (pep_update * 1000 * 2));}voidPEP::purge_old(){ struct timeval tv; click_gettimeofday(&tv); int i = 0; int j; for(j = 0; j < _entries.size(); j++){ if(tv.tv_sec - _entries[j]._when.tv_sec <= pep_purge){ _entries[i++] = _entries[j]; } else { if(_debug) click_chatter("PEP %s %s: purging old entry for %s (%d %d %d)", id().cc(), _my_ip.s().cc(), IPAddress(_entries[j]._fix.fix_id).s().cc(), (int) _entries[j]._when.tv_sec, (int) tv.tv_sec, pep_purge); } } static Entry dud; _entries.resize(i, dud);}voidPEP::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?boolPEP::sendable(Entry e){ struct timeval tv; click_gettimeofday(&tv); if(e._when.tv_sec + pep_stale > tv.tv_sec && e._fix.fix_hops < pep_max_hops){ return(true); } return(false);}voidPEP::externalize(pep_fix *fp){ fp->fix_seq = htonl(fp->fix_seq); fp->fix_hops = htonl(fp->fix_hops);}voidPEP::internalize(pep_fix *fp){ fp->fix_seq = ntohl(fp->fix_seq); fp->fix_hops = ntohl(fp->fix_hops);}Packet *PEP::make_PEP(){ WritablePacket *p = Packet::make(sizeof(pep_proto)); memset(p->data(), 0, p->length()); pep_proto *pp = (pep_proto *) p->data(); pp->id = _my_ip.addr(); int nf = 0; if(_fixed){ pep_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_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; pp->fixes[nf].fix_hops += 1; externalize(&(pp->fixes[nf])); nf++; } } pp->n_fixes = htonl(nf); return p;}intPEP::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("PEP %s %s: new entry for %s", this->id().cc(), _my_ip.s().cc(), IPAddress(id).s().cc()); 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 *PEP::simple_action(Packet *p){ int nf; pep_proto *pp; struct timeval tv; click_gettimeofday(&tv); if(p->length() != sizeof(pep_proto)){ click_chatter("PEP: bad size packet (%d bytes)", p->length()); goto out; } pp = (pep_proto *) p->data(); nf = ntohl(pp->n_fixes); if(nf < 0 || (const u_char*)&pp->fixes[nf] > p->data()+p->length()){ click_chatter("PEP: bad n_fixes %d", nf); goto out; } int i; for(i = 0; i < nf && i < pep_proto_fixes; i++){ pep_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 < oh)){ _entries[j]._fix = f; _entries[j]._when = tv; if(_debug && f.fix_hops != oh) click_chatter("PEP %s %s: updating %s, seq %d -> %d, hops %d -> %d, my pos %s", id().cc(), _my_ip.s().cc(), IPAddress(f.fix_id).s().cc(), os, f.fix_seq, oh, f.fix_hops, get_current_location().s().cc()); } } out: p->kill(); return(0);}// Actually guess where we are.grid_locationPEP::algorithm1(){ double lat = 0, lon = 0; double weight = 0; int i; struct timeval now; click_gettimeofday(&now); for(i = 0; i < _entries.size(); i++){ if(now.tv_sec - _entries[i]._when.tv_sec < pep_stale){ double w = 1.0 / (_entries[i]._fix.fix_hops + 1); lat += w * _entries[i]._fix.fix_loc.lat(); lon += w * _entries[i]._fix.fix_loc.lon(); weight += w; } } return(grid_location(lat / weight, lon / weight));}class PEPAmoeba : public Amoeba {public: PEPAmoeba () : Amoeba(2) { } double fn(double a[]); int _n; double _x[20]; double _y[20]; double _d[20];};doublePEPAmoeba::fn(double a[]){ double x = a[0]; double y = a[1]; double d = 0; int i; for(i = 0; i < _n; i++){ double dx = x - _x[i]; double dy = y - _y[i]; double dd = _d[i] - sqrt(dx*dx + dy*dy); dd = dd * dd; d += dd; } return(d);}grid_locationPEP::algorithm2(){ PEPAmoeba a; int i; struct timeval now; click_gettimeofday(&now); a._n = 0; for(i = 0; i < _entries.size() && a._n < 5; i++){ if(now.tv_sec - _entries[i]._when.tv_sec < pep_stale){ a._x[a._n] = _entries[i]._fix.fix_loc.lat(); a._y[a._n] = _entries[i]._fix.fix_loc.lat(); a._d[a._n] = _entries[i]._fix.fix_hops * 0.002; // XXX 250 meters? should be fix_hops + 1?? a._n += 1; } } double pts[2]; a.minimize(pts); return(grid_location(pts[0], pts[1]));}grid_locationPEP::get_current_location(){ if(_fixed) return(grid_location(_lat, _lon)); if(_entries.size() < 1) return(grid_location(0.0, 0.0)); return(algorithm1());}static Stringpep_read_handler(Element *f, void *){ PEP *l = (PEP *) f; return(l->s());}StringPEP::s(){ String s; int i, n; struct timeval now; click_gettimeofday(&now); if(_fixed){ s = _my_ip.s() + " " + grid_location(_lat, _lon).s() + "\n"; } else { s = _my_ip.s() + "\n"; } s += get_current_location().s() + "\n"; n = _entries.size(); for(i = 0; i < n; i++){ pep_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).s().cc(), f.fix_seq, f.fix_loc.s().cc(), f.fix_hops, (int)(now.tv_sec - _entries[i]._when.tv_sec)); s += buf; } return s;}voidPEP::add_handlers(){ add_default_handlers(true); add_read_handler("status", pep_read_handler, (void *) 0);}ELEMENT_REQUIRES(GridLocationInfo Amoeba)EXPORT_ELEMENT(PEP)#include <click/vector.cc>template class Vector<PEP::Entry>;CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -