📄 hgpsagent.cc
字号:
#include "hgpsagent.h"static class HGPSAgentClass : public TclClass{ public: HGPSAgentClass():TclClass("Agent/HGPSAgent") { } TclObject* create(int, const char *const *) { return (new HGPSAgent()); }}class_HGPSAgent;HGPSAgent::HGPSAgent() : Agent(PT_HGPS),verbose_(1),send_buf_timer(this){ router = new HGPSRouter(this); locserver = new LocServer(this); verbose_ = 1; sleepevent = new Event; sleephandler = new HGPSSleepHandler(this); locserver->setRouter(router); router->setLocServer(locserver); for (int i=0;i<SEND_BUF_SIZE;i++) { send_buf[i].p = NULL; send_buf[i].t = -999.0; } asleep = true; wakeup_time = 0.0; bind("off_HGPS_", &off_hgps_); bind("off_ll_", &off_ll_); bind("off_mac_", &off_mac_); bind("off_ip_", &off_ip_); bind("update_distance_", &update_distance_);}HGPSAgent::~HGPSAgent(){ fprintf(stderr,"DFU: Don't do this! I haven't figured out ~HGPSAgent too\n"); exit(-1);}voidHGPSAgent::trace(char* fmt, ...){ va_list ap; if (!logtarget) return; va_start(ap, fmt); vsprintf(logtarget->buffer(), fmt, ap); logtarget->dump(); va_end(ap);}voidHGPSAgent::startUp(){ wakeup_time = Scheduler::instance().clock(); assert(asleep == true); asleep = false; router->start(); locserver->start(); send_buf_timer.sched(BUFFER_CHECK + BUFFER_CHECK * Random::uniform(1.0)); real_ll->start();}voidHGPSAgent::sleep(){ assert(asleep == false); //stop hgpsrouter and locserver router->sleep(); locserver->sleep(); //cancel send_buf_timer send_buf_timer.force_cancel(); //kill all the packets in send buffer int c; for (c = 0 ; c < SEND_BUF_SIZE ; c++) { if (send_buf[c].p) { drop(send_buf[c].p, DROP_RTR_SLEEP); send_buf[c].p = NULL; } } //stop the link layer real_ll->sleep(); asleep = true;}intHGPSAgent::command(int argc, const char*const* argv){ TclObject *obj; if (argc == 2) { if (strcasecmp(argv[1], "reset") == 0) { Terminate(); return Agent::command(argc, argv); } if (strcasecmp(argv[1], "start-hgps") == 0) { startUp(); return TCL_OK; } } else if(argc == 3) { if (strcasecmp(argv[1], "ip-addr") == 0) { myaddr_ = atoi(argv[2]); return TCL_OK; } if (strcasecmp(argv[1],"wakeup") == 0) { startUp(); //schedule a sleeping timer Scheduler::instance().schedule(sleephandler,sleepevent,atof(argv[2])); return TCL_OK; } if (strcasecmp(argv[1], "test-query") == 0) { if (asleep) { return TCL_OK; } nsaddr_t dst= atoi(argv[2]); //hmmm, right now i just schedule an event first, if it's still too memory-consuming, then... Packet *p = allocpkt(); hdr_ip *iph = (hdr_ip*)p->access(off_ip_); hdr_cmn *cmnh = (hdr_cmn*)p->access(off_cmn_); hdr_hgps *hgpsh = (hdr_hgps*)p->access(off_hgps_); iph->dst() = dst; iph->src() = myaddr_; hgpsh->init(); hgpsh->type_ = DATA; cmnh->size() += IP_HDR_LEN; cmnh->size() = 128; //default cmnh->num_forwards() = 0; trace("S %.9f _%d_ originating pkt %d->%d",Scheduler::instance().clock(),myaddr_,iph->src(),iph->dst()); handlePktWithoutLoc(p,false); return TCL_OK; } if( (obj = TclObject::lookup(argv[2])) == 0) { fprintf(stderr, "HGPSAgent: %s lookup of %s failed\n", argv[1], argv[2]); return TCL_ERROR; } if (strcasecmp(argv[1],"mobile-node") == 0) { locserver->setMobileNode((MobileNode *)obj); return TCL_OK; } if (strcasecmp(argv[1], "log-target") == 0) { logtarget = (Trace*) obj; return TCL_OK; } if (strcasecmp(argv[1],"add-real-ll") == 0 ) { real_ll = (LL *) obj; return TCL_OK; } } else if (argc == 4) { if (strcasecmp(argv[1], "add-ll") == 0) { if( (obj = TclObject::lookup(argv[2])) == 0) { fprintf(stderr, "HGPSAgent: %s lookup of %s failed\n", argv[1], argv[2]); return TCL_ERROR; } ll = (NsObject*) obj; if( (obj = TclObject::lookup(argv[3])) == 0) { fprintf(stderr, "HGPSAgent: %s lookup of %s failed\n", argv[1], argv[3]); return TCL_ERROR; } ifq = (PriQueue *) obj; return TCL_OK; } } return Agent::command(argc, argv);}voidHGPSAgent::recv(Packet *p, Handler *){ hdr_ip *iph = (hdr_ip *) p->access (off_ip_); hdr_cmn *cmnh = (hdr_cmn *) p->access (off_cmn_); hdr_hgps *hgpsh = (hdr_hgps*)p->access(off_hgps_); if (asleep) { //drop the packet drop(p,DROP_RTR_SLEEP); return; } /* * Must be a packet I'm originating... */ if(iph->src_ == myaddr_ && cmnh->num_forwards() == 0) { iph->ttl_ = HGPS_IP_DEF_TTL; } /* * Packet I'm forwarding... */ else { /* * Check the TTL. If it is zero, then discard. */ if(--iph->ttl_ == 0) { drop(p, DROP_RTR_TTL); return; } } if (!hgpsh->valid_) { hgpsh->init(); hgpsh->type_ = DATA; iph->src() = myaddr_; cmnh->size() += IP_HDR_LEN; cmnh->num_forwards() = 0; trace("S %.9f _%d_ originating pkt %d->%d",Scheduler::instance().clock(),myaddr_,iph->src(),iph->dst());#ifdef HGPS_DEBUG150 assert((iph->dst()>0)&& (iph->dst()<=150));#endif handlePktWithoutLoc(p,false); }else{ if (hgpsh->type_ == LOC_QUERY) { hgpsh->query_forwards_++; }else if (hgpsh->type_ == LOC_QUERY_RESPONSE) { hgpsh->query_response_forwards_++; } forwardHGPSPkt(p); }}voidHGPSAgent::forwardHGPSPkt(Packet *p){ hdr_ip *iph = (hdr_ip *) p->access (off_ip_); hdr_hgps *hgpsh = (hdr_hgps*)p->access(off_hgps_); //take different actions based on the type of packet if (hgpsh->type_ == LOC_UPDATE) { locserver->recvUpdate(p); }else if (hgpsh->type_ == LOC_UPDATE_FP) { locserver->recvFPUpdate(p); }else if (hgpsh->type_ == ROUTE_UPDATE) { router->recvNeighborUpdate(p); }else if ((hgpsh->type_ == LOC_QUERY)) { locserver->recvQuery(p,false); }else { if (iph->dst() == myaddr_) { handlePktReceipt(p); }else { router->sendOutPktWithLocation(p,0.0,true); } }}voidHGPSAgent::handlePktWithoutLoc(Packet *&p,bool retry){ hdr_ip *iph = (hdr_ip *)p->access(off_ip_); hdr_cmn *cmnh = (hdr_cmn *)p->access (off_cmn_); hdr_hgps *hgpsh = (hdr_hgps*)p->access(off_hgps_); Scheduler & s = Scheduler::instance(); //try to see if I'm lucky enough that the dstination is only 2 hops away if ((cmnh->next_hop() = router->getNextHopFromNT(iph->dst(), hgpsh->dst_loc_))) {#ifdef TEST_QUERY //drop(p,DROP_IFQ_ARP_FULL); Packet::free(p); return;#endif if (verbose_) { trace("S$hit NT %.5f _%d_ %d->%d",s.clock(),myaddr_,iph->src(),iph->dst()); } hgpsh->src_loc_ = locserver->getGrid(); s.schedule(ll,p,0); p = NULL; return; }#ifdef TEST_WS //if God says the destination is not awake yet if (!God::instance()->isAwake(iph->dst())) { drop(p, DROP_RTR_SLEEP); return; }#endif //I have to find out the dst location first! if (locserver->getLocation(iph->dst(),hgpsh->dst_loc_)) {#ifndef TEST_QUERY if (hgpsh->dst_loc_.loc != -1) { hgpsh->src_loc_ = locserver->getGrid(); router->sendOutPktWithLocation(p,0.0,false); p = NULL; return; }#endif } //stick packet in send buffer#ifndef TEST_QUERY if (!retry) { stickPacketInSendBuffer(p); }#endif#ifdef TEST_QUERY //drop(p,DROP_IFQ_ARP_FULL); Packet::free(p); return;#endif if (verbose_) { trace("S$miss %.5f _%d_ %d->%d",s.clock(),myaddr_,iph->src(),iph->dst()); }}voidHGPSAgent::handlePktReceipt(Packet *p){ hdr_ip *iph = (hdr_ip *) p->access (off_ip_); hdr_cmn *cmh = (hdr_cmn *) p->access (off_cmn_); hdr_hgps *hgpsh = (hdr_hgps*)p->access(off_hgps_); if (hgpsh->type_ == DATA) { //log the src location information locserver->addUpdateLiveConn(iph->src(),hgpsh->src_loc_); locserver->updateLocCache(iph->src(),hgpsh->src_loc_,CACHE_TIMEOUT); //send it to the upper layer cmh->size() = cmh->size() - IP_HDR_LEN - hgpsh->size(); hgpsh->valid_ = 0; target_->recv(p,(Handler*)0); return; } if (hgpsh->type_ == ERR) { //this is a location err, i should purge the location information of the destination locserver->purgeLocCache(hgpsh->id_); Packet::free(p); return; } if (hgpsh->type_ == LOC_NOTIFICATION) { //this is a location change notification, change my cache entires accordingly locserver->updateLocCache(iph->dst(),hgpsh->dst_loc_, CACHE_TIMEOUT); Packet::free(p); return; } if (hgpsh->type_ == LOC_QUERY) { locserver->recvQuery(p,false); return; } if (hgpsh->type_ == LOC_QUERY_RESPONSE) { locserver->recvQueryResponse(p); return; }}/* this function is called by locserver when a LOC_QUERY_RESPONSE is received */voidHGPSAgent::notifyLocation(nsaddr_t id, location loc){ int c; hdr_ip *iph; hdr_hgps *hgpsh; double delay = 0.0; for (c=0; c< SEND_BUF_SIZE;c++) { if (send_buf[c].p == NULL) continue; iph = (hdr_ip *)(send_buf[c].p)->access(off_ip_); if (iph->dst() == id) { hgpsh = (hdr_hgps *)(send_buf[c].p)->access(off_hgps_); hgpsh->dst_loc_ = loc; hgpsh->src_loc_ = locserver->getGrid(); router->sendOutPktWithLocation(send_buf[c].p,delay,true); assert(send_buf[c].p == NULL); delay = delay + ARP_TIMEOUT; } }}voidHGPSAgent::Terminate(){ int c; for (c = 0 ; c < SEND_BUF_SIZE ; c++) { if (send_buf[c].p) { drop(send_buf[c].p, DROP_END_OF_SIMULATION); send_buf[c].p = NULL; } }}/* -------------- below are sendbuf related functions ----------------- */voidHGPSAgent::stickPacketInSendBuffer(Packet *p){ double min = 99999.0;//initialize min to some big enough number int min_index = 0; int c; hdr_ip *iph = (hdr_ip *) p->access (off_ip_); if (verbose_) trace("Sdebug %.5f _%d_ stuck into send buff %d -> %d", Scheduler::instance().clock(), myaddr_, iph->src(),iph->dst()); for (c = 0 ; c < SEND_BUF_SIZE ; c ++) if (send_buf[c].p == NULL) { send_buf[c].t = Scheduler::instance().clock(); send_buf[c].p = p; return; } else if (send_buf[c].t < min) { min = send_buf[c].t; min_index = c; } // kill somebody dropSendBuff(send_buf[min_index].p); assert(send_buf[min_index].p == NULL); send_buf[min_index].t = Scheduler::instance().clock(); send_buf[min_index].p = p;}voidHGPSAgent::dropSendBuff(Packet *&p) // log p as being dropped by the sendbuffer in HGPS agent{ hdr_ip *iph = (hdr_ip *) p->access (off_ip_); trace("Ssb %.5f _%d_ dropped %d -> %d", Scheduler::instance().clock(), myaddr_, iph->src(), iph->dst()); drop(p, DROP_RTR_QTIMEOUT); p = NULL;}voidHGPSAgent::sendBufferCheck() // see if any packets in send buffer need route requests sent out // for them, or need to be expired{ // this is called about once a second. run everybody through the // get route for pkt routine to see if it's time to do another // location query or what not int c; for (c = 0 ; c <SEND_BUF_SIZE ; c++) { if (send_buf[c].p == NULL) continue; if ((Scheduler::instance().clock() - send_buf[c].t)> SEND_TIMEOUT) { dropSendBuff(send_buf[c].p); send_buf[c].p = NULL; continue; }#ifdef HGPS_DEBUG hdr_ip *iph = (hdr_ip *)send_buf[c].p->access(off_ip_); trace("Sdebug %.5f _%d_ checking for route for dst %d", Scheduler::instance().clock(), myaddr_, iph->dst());#endif handlePktWithoutLoc(send_buf[c].p, true);#ifdef HGPS_DEBUG hdr_ip *iph = (hdr_ip *)send_buf[c].p->access(off_ip_); if (send_buf[c].p == NULL) trace("Sdebug %.5f _%d_ sendbuf pkt to %d liberated by handlePktWOSR", Scheduler::instance().clock(), myaddr_; iph->src());#endif }}voidHGPSSendBufferTimer::expire(Event *e){ a_->sendBufferCheck(); resched(BUFFER_CHECK + BUFFER_CHECK * (double) ((int) e>>5 & 0xff) / 256.0);}voidHGPSSleepHandler::handle(Event *e){ a_->sleep();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -