📄 cbrpagent.cc
字号:
// sendOutPacketWithRoute will add in the size of the src hdr, so // we have to subtract it out here struct hdr_cmn *ch = HDR_CMN(p.pkt); if (cbrph->route_shortening()) { //the previous node has successfully shortened one node for (int c = (cbrph->cur_addr()-1); c < cbrph->num_addrs()-1 ; c++) { cbrph->addrs[c].addr = cbrph->addrs[c+1].addr; p.route[c].addr = p.route[c+1].addr; } cbrph->cur_addr() -= 1; p.route.setIterator(cbrph->cur_addr()); cbrph->num_addrs()-= 1; p.route.setLength(cbrph->num_addrs()); cbrph->route_shortening() = 0; cbrph->route_shortened() = 1; trace("CBRP %.5f _%d_ success-shorten %s", Scheduler::instance().clock(),myaddr_, p.route.dump()); } ch->size() -= cbrph->size(); sendOutPacketWithRoute(p, false);}intCBRP_Agent::handleRREP(CBRP_Packet &p){ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); hdr_cmn *cmnh = (hdr_cmn*)p.pkt->access(off_cmn_); cmnh->addr_type() = AF_INET; cmnh->xmit_failure_ = CBRP_XmitFailureCallback; cmnh->xmit_failure_data_ = (void *) this; //just a cautionary step... if (p.route.length()<=0) {#ifdef CBRP_DEBUG printf("ERROR route len %d\n", p.route.length()); printf("p.src %s, p.dest %s, me %s, route-reply %s\n", p.src.dump(),p.dest.dump(),net_id.dump(),return_reply_path(p.pkt, off_cbrp_));#endif abort(); } if ((cbrph->cur_addr() >= 0) && (p.route[p.route.index()] == net_id) && (ntable->my_status == CLUSTER_HEAD)) { // I am the cluster head and have to calculate the route cbrph->cur_addr()--; if (cbrph->cur_addr()<0) { //i am the first cluster head, should be able to reach src if (ntable->isNeighbor(p.dest.getNSAddr_t())) { cmnh->next_hop() = p.dest.getNSAddr_t(); }else { if (!(cmnh->next_hop()=ntable->GetQuickNextNode(p.dest.getNSAddr_t()))) { trace("CBRP %.5f _%d_ drop-reply-no-route unable return route to %s",Scheduler::instance().clock(), myaddr_,p.dest.dump()); Packet::free(p.pkt); p.pkt = NULL; return 0; } } //if there is a link between next hop and the previous calculated hop, i am bypassed. //otherwise include me in the calculated route. //Right now, the head won't search in its two-hop-topology table //for a non-cluster-head guy to take off its work as the current 2-hop topology table //implementation is not complete. A more efficient data structure //has to be implemented to speed up the search. :) if (!ntable->existsLink(cmnh->next_hop(), (cbrph->reply_addrs()[cbrph->route_reply_len()-1]).addr)) { (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr = net_id.addr; (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr_type = AF_INET; cbrph->route_reply_len()++; } cmnh->prev_hop_ = net_id.getNSAddr_t(); cmnh->size() = cbrph->size(); Scheduler::instance().schedule(ll, p.pkt, 0); goto done; } // I am not the first cluster head, I'll try to reach the prev. cluster head nsaddr_t prev_cluster = (cbrph->addrs)[cbrph->cur_addr_].addr; nsaddr_t next_node = (cbrph->reply_addrs()[cbrph->route_reply_len()-1]).addr; // firstly try to reach the prev_cluster by 2 hops adjtable_ent *ent = ntable->GetAdjEntry(prev_cluster,1); if (ent == NULL) { //if i could not reach prev_cluster by 2 hops, try 3-hop gateway. ent = ntable->GetAdjEntry(prev_cluster, 0); } if (ent == NULL) { //I failed to reach prev_cluster trace("CBRP %.5f _%s_ drop-reply-no-route #%d (route reply %s -> %s cannot reach prev cluster %d on route %s) previous hop %d", Scheduler::instance().clock(), net_id.dump(), cbrph->rtreq_seq(), p.src.dump(), p.dest.dump(),prev_cluster, p.route.dump(), cmnh->prev_hop_); Packet::free(p.pkt); p.pkt = NULL; return 0; } nexthop_ent *next_hop = ent->next_hop; assert(next_hop != NULL); while (next_hop) { //try to search for a gateway node that could be directly reached by route's next node //therefore, bypassing me. if (ntable->existsLink(next_hop->next_node,next_node)) { cmnh->next_hop() = next_hop->next_node; cmnh->addr_type() = AF_INET; break; } next_hop = next_hop->next; } if (next_hop == NULL) { cmnh->next_hop() = ent->next_hop->next_node; assert(cmnh->next_hop()>0); // it has to go pass me. -Jinyang (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr = net_id.addr; (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr_type = AF_INET; cbrph->route_reply_len()++; } cmnh->size() = cbrph->size(); cmnh->prev_hop_ = net_id.getNSAddr_t(); Scheduler::instance().schedule(ll, p.pkt, 0); } else { //I am an ordinary node non-CLUSTER_HEAD nsaddr_t next_cluster; //if I am just an ordinary node, I just forward it to the next cluster head cmnh->addr_type() = AF_INET; if (cbrph->cur_addr_<0) { //I am supposed to be two hop away from the destination node next_cluster = p.dest.addr; if (ntable->isNeighbor(next_cluster)) { cmnh->next_hop() = next_cluster; }else { cmnh->next_hop() = ntable->GetQuickNextNode(next_cluster); if (!cmnh->next_hop()) { trace("CBRP %.5f _%d_ drop-reply-no-route %s->%s #%d (route reply cannot reach prev cluster %d)",Scheduler::instance().clock(), myaddr_,p.src.dump(), p.dest.dump(), cbrph->rtreq_seq(),next_cluster); Packet::free(p.pkt); p.pkt = NULL; return 0; } } }else { //try to reach the next_cluster head. next_cluster = cbrph->addrs[cbrph->cur_addr()].addr; //check if the neighbor cluster is just one hop away if (ntable->isNeighbor(next_cluster)) { cmnh->next_hop() = next_cluster; } else { cmnh->next_hop() = ntable->GetQuickNextNode(next_cluster); if (!cmnh->next_hop()) { trace("CBRP %.5f _%d_ drop-reply-no-route %s->%s #%d (route reply cannot reach prev cluster %d)", Scheduler::instance().clock(), myaddr_,p.src.dump(), p.dest.dump(), cbrph->rtreq_seq(),next_cluster); Packet::free(p.pkt); p.pkt = NULL; return 0; } } } //checking for wrong route reply calculation which could cause looping. int i; for (i=cbrph->route_reply_len();i>0;i--) { if (cbrph->reply_addrs()[i-1].addr == cmnh->next_hop()) { break; } } if (i>0) { trace("CBRP %.5f _%d_ drop-reply-looped %s->%s #%d existing route:%s reaching next cluster %d via %d",Scheduler::instance().clock(),myaddr_, p.src.dump(), p.dest.dump(), cbrph->rtreq_seq(),p.route.dump(),next_cluster,cmnh->next_hop()); Packet::free(p.pkt); p.pkt = NULL; return 0; } //add myself to the route reply (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr = net_id.addr; (cbrph->reply_addrs()[cbrph->route_reply_len()]).addr_type = AF_INET; cbrph->route_reply_len()++; cmnh->prev_hop_ = net_id.getNSAddr_t(); cmnh->size() = cbrph->size(); //Scheduler::instance().schedule(ll, p.pkt, Random::uniform(RREQ_JITTER)); Scheduler::instance().schedule(ll, p.pkt,0 ); }done:#ifdef CBPR_DEBUG trace("cbrp _%d_ route-reply-sent %s #%d -> %s , next hop %d to reach %d, rest of recorded cluster heads %s, constructed return path %s", myaddr_, p.src.dump(),cbrph->rtreq_seq(), p.dest.dump(), cmnh->next_hop(),(cbrph->cur_addr()>-1)?cbrph->addrs[cbrph->cur_addr()].addr:iph->dst(),p.route.dump(),return_reply_path(p.pkt, off_cbrp_)); #endif p.pkt = NULL; return 1;}voidCBRP_Agent::handleRREQ(CBRP_Packet &p) /* process a route request that isn't targeted at us cluster heads will broadcast RREQ to all chosen gateways Chosen gateways will unicast RREQ to neighbor cluster head*/{ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); hdr_ip *iph = (hdr_ip*)p.pkt->access(off_ip_); assert (cbrph->route_request()); if ((u_int32_t)iph->dst() != IP_BROADCAST) { //I am the neighborcluster head, i should broadcast this RREQ to my neighbors if (ntable->my_status == CLUSTER_HEAD || (iph->dst() == myaddr_)) { BroadcastRREQ(p); }else { //i should forward packet to the clusterhead as specified in ip destination //this could happen when the neighbor cluster head is 3 hops away and I am the second gateway UnicastRREQ(p,iph->dst()); } }else { Packet *p_ori = p.pkt; for (int i=0;i<cbrph->num_forwarders();i++) { if (cbrph->forwarders[i].which_gateway == myaddr_) { p.pkt = p_ori->copy(); if ((cbrph->forwarders[i].which_head == myaddr_) && (ntable->my_status == CLUSTER_HEAD)) { //broadcast the pkt to other cluster heads BroadcastRREQ(p); }else { // if I am just an ordinary node, then just forward the RREQ as indicated in header UnicastRREQ(p,cbrph->forwarders[i].which_head); } } } // discard un-used RREQ packet if (p_ori) Packet::free(p_ori); } p.pkt = NULL;}voidCBRP_Agent::BroadcastRREQ(CBRP_Packet &p){ hdr_cbrp *cbrph = (hdr_cbrp*)p.pkt->access(off_cbrp_); hdr_cmn *cmnh = (hdr_cmn*)p.pkt->access(off_cmn_); hdr_ip *iph = (hdr_ip*)p.pkt->access(off_ip_); assert(cbrph->route_request()); if (ignoreRouteRequestp(p)) { //-Jinyang only cluster heads records RREQs seen and drop RREQ if duplicate etc. if (verbose_srr) trace("cbrp %.5f _%s_ dropped %s #%d (ignored)", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), cbrph->rtreq_seq()); Packet::free(p.pkt); // pkt is a route request we've already processed return; // drop silently } request_table.insert(p.src, p.src, cbrph->rtreq_seq()); if (p.route.length() > (cbrph->max_propagation()/2)) // the chain of cluster heads are roughly twice as long as the hop by hop route { if (verbose_srr) trace("cbrp %.5f _%s_ dropped %s #%d (prop limit exceeded)", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), cbrph->rtreq_seq()); Packet::free(p.pkt); // pkt isn't for us, and isn't data carrying p.pkt = 0; return; } if ((2*p.route.length()) > MAX_SR_LEN) { // no propagation trace("cbrp %.5f _%s_ dropped %s #%d (SR full)", Scheduler::instance().clock(), net_id.dump(), p.src.dump(), cbrph->rtreq_seq()); Packet::free(p.pkt); p.pkt = 0; return; } p.route.appendToPath(net_id); fillCBRPPath(p.route,cbrph); cmnh->ptype() = PT_CBRP; cmnh->addr_type() = AF_INET; if (ntable->isNeighbor(cbrph->request_destination())) { //directly unicast to the destination cmnh->next_hop() = cbrph->request_destination(); iph->dst() = cbrph->request_destination(); cbrph->num_forwarders() = 0; cmnh->size() = cbrph->size(); Scheduler &s = Scheduler::instance(); s.schedule(ll,p.pkt,0.0); return; }#ifdef CBRP_DEBUG trace("cbrp RREQ %d: %s",myaddr_,ntable->printNeighbors());#endif if (ntable->GetQuickNextNode(cbrph->request_destination())) { iph->dst() = cbrph->request_destination(); cmnh->next_hop() = ntable->GetQuickNextNode(cbrph->request_destination()); cbrph->num_forwarders() = 0; cmnh->size() = cbrph->size(); Scheduler::instance().schedule(ll,p.pkt,0.0); p.pkt = 0; return; } if (cbrp_reply_from_cache_on_propagating && replyFromRouteCache(p)) { p.pkt = NULL; return; } cmnh->next_hop() = MAC_BROADCAST; iph->dst() = IP_BROADCAST; int total = cbrph->num_forwarders(); Packet *p_copy = p.pkt->copy(); hdr_cbrp *new_cbrph = (hdr_cbrp*)p_copy->access(off_cbrp_); adjtable_ent *p_adj = ntable->adjtable_1; int i=0; int j=0; while (p_adj && i<MAX_NEIGHBORS) { //check if a neighbor cluster head has been visited b4 by this RREQ by checking its recorded route so far if (p.route.member(ID(p_adj->neighbor_cluster, ::IP))) {#ifdef CBRP_DEBUG trace("cbrp RREQ%d: ignored %d, duplicate in route(%s)",myaddr_,p_adj->neighbor_cluster,p.route.dump());#endif p_adj = p_adj->next; continue; } //check if a neighbor cluster will have been visited by prev. cluster head by checking the forwarders' list for (j=0;j<total;j++) { if (p_adj->neighbor_cluster == cbrph->forwarders[j].which_head) {#ifdef CBRP_DEBUG trace("cbrp RREQ%d: ignored %d, duplicate in previous broadcast",myaddr_,p_adj->neighbor_cluster);#endif break; } } if (j>= total) { //the next cluster head has NOT been visited to the best of our knowledge. :)#ifdef CBRP_DEBUG trace("cbrp %.5f _%s_ rebroadcast %s #%d ->%d %s to 2 hop head %d via %d",Scheduler::instance().clock(), net_id.dump(), p.src.dump(), cbrph->rtreq_seq(), cbrph->request_destination(), p.route.dump(), p_adj->neighbor_cluster, p_adj->next_hop->next_node);#endif /*new_cbrph->reply_addrs()[i].which_gateway= p_adj->next_hop->next_node; */ new_cbrph->forwarders[i].which_gateway= ntable->GetQuickNextNode(p_adj->neighbor_cluster); new_cbrph->forwarders[i++].which_head= p_adj->neighbor_cluster; } p_adj = p_adj->next; } //if I am not a cluster head, i don't send RREQ to 3-hop neighbor cluster head if (ntable->my_status != CLUSTER_HEAD) { goto DONE; } p_adj = ntable->adjtable_2; while (p_adj && i<MAX_NEIGHBORS) { if (p.route.member(ID(p_adj->neighbor_cluster, ::IP))) {#ifdef CBRP_DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -