📄 cbrpagent.cc
字号:
ifq = (PriQueue *) obj; return TCL_OK; } }return (Agent::command (argc, argv));}/*=========================================================================== SendBuf management and helpers -- from cmu/dsr/cbrp.cc by dmaltz---------------------------------------------------------------------------*/voidCBRP_SendBufferTimer::expire(Event *e) { a_->sendBufferCheck(); resched(BUFFER_CHECK + BUFFER_CHECK * (double) ((int) e>>5 & 0xff) / 256.0);}voidCBRP_Agent::dropSendBuff(CBRP_Packet &p) // log p as being dropped by the sendbuffer in CBRP agent{ trace("Ssb %.5f _%s_ dropped %s -> %s", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), p.dest.dump()); drop(p.pkt, DROP_RTR_QTIMEOUT); p.pkt = 0; p.route.reset();}voidCBRP_Agent::stickPacketInSendBuffer(CBRP_Packet& p){ Time min = DBL_MAX; int min_index = 0; int c; if (verbose_) trace("Sdebug %.5f _%s_ stuck into send buff %s -> %s", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), p.dest.dump()); for (c = 0 ; c < SEND_BUF_SIZE ; c ++) if (send_buf[c].p.pkt == 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); send_buf[min_index].t = Scheduler::instance().clock(); send_buf[min_index].p = p;}voidCBRP_Agent::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 // route request or what not int c; for (c = 0 ; c <SEND_BUF_SIZE ; c++) { if (send_buf[c].p.pkt == NULL) continue; if (Scheduler::instance().clock() - send_buf[c].t > SEND_TIMEOUT) { dropSendBuff(send_buf[c].p); send_buf[c].p.pkt = 0; continue; }#ifdef DEBUG trace("Sdebug %.5f _%s_ checking for route for dst %s", Scheduler::instance().clock(), net_id.dump(), send_buf[c].p.dest.dump());#endif handlePktWithoutSR(send_buf[c].p, true);#ifdef DEBUG if (send_buf[c].p.pkt == NULL) trace("Sdebug %.5f _%s_ sendbuf pkt to %s liberated by handlePktWOSR", Scheduler::instance().clock(), net_id.dump(), send_buf[c].p.dest.dump());#endif }}/*============================================================== Route Request backoff -dmaltz------------------------------------------------------------*/static boolBackOffTest(Entry *e, Time time)// look at the entry and decide if we can send another route// request or not. update entry as well{ Time next = ((Time) (0x1<<(e->rt_reqs_outstanding*2))) * cbrp_rt_rq_period; if (next > cbrp_rt_rq_max_period) next = cbrp_rt_rq_max_period; if (next + e->last_rt_req > time) return false; // don't let rt_reqs_outstanding overflow next on the LogicalShiftsLeft's if (e->rt_reqs_outstanding < 15) e->rt_reqs_outstanding++; e->last_rt_req = time; return true;}voidCBRP_Agent::Terminate(){ int c; for (c = 0 ; c < SEND_BUF_SIZE ; c++) { if (send_buf[c].p.pkt) { drop(send_buf[c].p.pkt, DROP_END_OF_SIMULATION); send_buf[c].p.pkt = 0; } }}voidCBRP_Agent::testinit(){ struct hdr_cbrp hsr; if (net_id == ID(1,::IP)) { printf("adding route to 1\n"); hsr.init(); hsr.append_addr( 1, AF_INET ); hsr.append_addr( 2, AF_INET ); hsr.append_addr( 3, AF_INET ); hsr.append_addr( 4, AF_INET ); route_cache->addRoute(Path(hsr.addrs, hsr.num_addrs()), 0.0, ID(1,::IP)); } if (net_id == ID(3,::IP)) { printf("adding route to 3\n"); hsr.init(); hsr.append_addr( 3, AF_INET ); hsr.append_addr( 2, AF_INET ); route_cache->addRoute(Path(hsr.addrs, hsr.num_addrs()), 0.0, ID(3,::IP)); }}/*-------------from here onwards, we deal with more CBRP specific stuff---*/void CBRP_Agent::forwardSRPacket(Packet* packet){ hdr_cbrp *cbrph = (hdr_cbrp*)packet->access(off_cbrp_); hdr_ip *iph = (hdr_ip*)packet->access(off_ip_); hdr_cmn *cmh = (hdr_cmn*)packet->access(off_cmn_); assert(cmh->size() >= 0); CBRP_Packet p(packet, cbrph); p.dest = ID(iph->dst(),::IP); p.src = ID(iph->src(),::IP); assert(logtarget != 0); if (!cbrph->valid()) { // this must be an outgoing packet, it doesn't have a SR header on it cbrph->init(); // give packet an SR header now if (verbose_) trace("S %.9f _%s_ originating %s -> %s", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), p.dest.dump()); cmh->size() += IP_HDR_LEN; cmh->ptype() = PT_CBR; handlePktWithoutSR(p, false); goto done; } if ( ((p.dest == net_id) && (!cbrph->route_request())) || ((p.dest == IP_broadcast) && (!cbrph->route_request())) || (cbrph->route_request() && ((unsigned long)cbrph->request_destination() == net_id.addr)) ) { //this is either a route_reply for my previously sent-out RREQ or a data packet for me //or a route_request searching for me handlePacketReceipt(p); goto done; } // should we check to see if it's an error packet we're handling // and if so call processBrokenRouteError to snoop if (cbrp_snoop_forwarded_errors && cbrph->route_error()) { processBrokenRouteError(p); } if (cbrph->route_request()) { // propagate a route_request that's not for us //if I am not a cluster head, forward the RREQ as indicated to p.dest //if I am cluster head, broadcast to other un-visited neighboring clusters handleRREQ(p); } else if (!cbrph->route_repaired() && !cbrph->route_shortened() && cbrph->route_reply()) { //if I am cluster head, i have to calculate part of the RREP //if I am oridnary node, record myself in RREP and forward it to the next cluster head handleRREP(p); } else { // we're not the intended final receipient, but we're a hop along the route // since repaired route is hop by hop, we will use normal data packet forwarding // function to handle it handleForwarding(p); }done: assert(p.pkt == 0); return;}/*--------------------------------------------------------------------------= different packet handling functions, ---------------------------------------------------------------------------*/voidCBRP_Agent::handlePktWithoutSR(CBRP_Packet& p, bool retry) /* obtain a source route to p's destination and send it off. this should be a retry if the packet is already in the sendbuffer */{ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); hdr_ip *iph = (hdr_ip*)p.pkt->access(off_ip_); hdr_cmn *ch = (hdr_cmn*)p.pkt->access(off_cmn_); assert(cbrph->valid()); assert(iph->src() == myaddr_); if (p.dest == net_id) { // it doesn't need a source route, 'cause it's for us handlePacketReceipt(p); return; } //firstly, try our route cache to see if the route has been discovered if (route_cache->findRoute(p.dest, p.route, 1)) { // lucky! we've got a route... if (verbose_) trace("S$hit %.5f _%s_ %s -> %s %s", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), p.dest.dump(), p.route.dump()); sendOutPacketWithRoute(p, true); return; } //secondly, examine neighborhood table to see if destination node is our neighbor if (ntable->isNeighbor(p.dest.addr)) { p.route.reset(); p.route.appendToPath(net_id); p.route.appendToPath(p.dest); if (verbose_) { trace("S$direct hit %.5f _%s_ %d -> %s %s", Scheduler::instance().clock(), net_id.dump(), iph->src(), p.dest.dump(), p.route.dump()); } sendOutPacketWithRoute(p, true); return; } //thirdly, we'll check using two-hop-neighbor table if we could reach // the destination using only one intermediate node if (ntable->GetQuickNextNode(p.dest.addr)) { p.route.reset(); p.route.appendToPath(net_id); p.route.appendToPath(ID(ntable->GetQuickNextNode(p.dest.addr),::IP)); p.route.appendToPath(p.dest); if (verbose_) { trace("S$direct hit %.5f _%s_ %d -> %s %s", Scheduler::instance().clock(), net_id.dump(), iph->src(), p.dest.dump(), p.route.dump()); } sendOutPacketWithRoute(p, true); return; } // We have to send out a RREQ to discover the destination if (verbose_) trace("S$miss %.5f _%s_ %s -> %s retry %d", Scheduler::instance().clock(), net_id.dump(), net_id.dump(), p.dest.dump(), retry?1:0); getRouteForPacket(p, retry);}voidCBRP_Agent::handlePacketReceipt(CBRP_Packet& p) /* Handle a packet destined to us */{ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); if (cbrph->route_reply()) { //we've got a route_reply! acceptRREP(p); } if (cbrph->route_request()) { assert((unsigned long)cbrph->request_destination() == net_id.addr || net_id == p.dest); if (cbrp_reply_only_to_first_rtreq && ignoreRouteRequestp(p)) { //we only respond to the first route request // we receive from a host Packet::free(p.pkt); // drop silently p.pkt = 0; return; } else { // we're going to process this request now, so record the req_num request_table.insert(p.src, p.src, cbrph->rtreq_seq()); //initiate a RREP in reply to the RREQ returnSrcRouteToRequestor(p); } } if (cbrph->route_error()) { // register the dead route processBrokenRouteError(p); } if (cbrph->route_shortening()) { //the previous route shortening attempt is successful, shorten the route for (int c = (cbrph->cur_addr()-1); c < cbrph->num_addrs()-1 ; c++) { p.route[c].addr = p.route[c+1].addr; } p.route.setLength(cbrph->num_addrs()-1); cbrph->route_shortened() = 1; cbrph->route_shortening() = 0; } if (!cbrph->route_reply() && (unsigned long)cbrph->addrs[0].addr == p.src.addr && (cbrph->route_shortened() || cbrph->route_repaired())) { CBRP_Packet p_copy = p; p_copy.pkt = allocpkt(); p_copy.dest = p.src; p_copy.src = net_id; hdr_ip *new_iph = (hdr_ip*)p_copy.pkt->access(off_ip_); hdr_cbrp *new_cbrph = (hdr_cbrp*)p_copy.pkt->access(off_cbrp_); new_cbrph->init(); new_cbrph->route_repaired() = cbrph->route_repaired(); new_cbrph->route_shortened() = cbrph->route_shortened(); new_cbrph->route_reply() = 1; new_iph->src() = net_id.addr; new_iph->dst() = p.src.addr; new_iph->dport() = RT_PORT; new_iph->sport() = RT_PORT; new_iph->ttl() = 255; p_copy.route.reverseInPlace(); p_copy.route.resetIterator(); fillCBRPPath(p_copy.route,new_cbrph); hdr_cmn *new_cmnh = (hdr_cmn*)p_copy.pkt->access(off_cmn_); new_cmnh->ptype() = PT_CBRP; sendOutPacketWithRoute(p_copy,1); } target_->recv(p.pkt, (Handler*)0); p.pkt = 0;}voidCBRP_Agent::handleForwarding(CBRP_Packet &p) /* forward packet on to next host in source route, snooping as appropriate */{ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); hdr_cmn *cmh = (hdr_cmn*)p.pkt->access(off_cmn_); trace("cbrp %.9f _%s_ --- %d [%s -> %s] %s", Scheduler::instance().clock(), net_id.dump(), cmh->uid(), p.src.dump(), p.dest.dump(), cbrph->dump()); // first make sure we are the ``current'' host along the source route. // if we're not, the previous node set up the source route incorrectly. assert(p.route[p.route.index()] == net_id || p.route[p.route.index()] == MAC_id); if (p.route.index() >= p.route.length()) { fprintf(stderr,"dfu: ran off the end of a source route\n"); trace("SDFU: ran off the end of a source route\n"); drop(p.pkt, DROP_RTR_ROUTE_LOOP); p.pkt = 0; // maybe we should send this packet back as an error... return; } // if there's a source route, maybe we should snoop it too, does not do it by default if (cbrp_snoop_source_routes) route_cache->noticeRouteUsed(p.route, Scheduler::instance().clock(), net_id);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -