📄 imep.cc
字号:
l->lastSeq() = s; // advance sequence number for this neighbor stats.num_recvd_from_queue++; imep_object_process(p); Packet::free(p); // now deliver as many in sequence packets to ULP as possible Packet *p0; while((p0 = incomingQ.getPacket(index, l->lastSeq() + 1))) { if (verbose) trace("T %.9f _%d_ inorder - src %d seq %d (chain" " timer delivery)", CURRENT_TIME, ipaddr, HDR_IP(p0)->saddr(), l->lastSeq() + 1); l->lastSeq() += 1; stats.num_recvd_from_queue++; imep_object_process(p0); Packet::free(p0); } } if((expire = incomingQ.getNextExpire()) != 0.0) { assert(expire > CURRENT_TIME); if (verbose) trace("T %.9f _%d_ inorder - timer started (delay %.9f)", CURRENT_TIME, ipaddr, expire - CURRENT_TIME); incomingTimer.start(expire - CURRENT_TIME); }}//////////////////////////////////////////////////////////////////////voidimepAgent::scheduleReXmit(Packet *p){ rexmitq.insert(CURRENT_TIME + RETRANS_PERIOD, p, MAX_REXMITS); // start the timer if (!rexmitTimer.busy()) rexmitTimer.start(RETRANS_PERIOD); }voidimepAgent::scheduleIncoming(Packet *p, u_int32_t s){ struct hdr_ip *ip = HDR_IP(p); incomingQ.addEntry(ip->saddr(), CURRENT_TIME + MAX_RETRANS_TIME, s, p); // start the timer if (!incomingTimer.busy()) { if (verbose) trace("T %.9f _%d_ inorder - timer started", CURRENT_TIME, ipaddr); incomingTimer.start(MAX_RETRANS_TIME); }}// ======================================================================// Packet Processing FunctionsvoidimepAgent::recv(Packet *p, Handler *){ //struct hdr_ip *ih = HDR_IP(p); struct hdr_cmn *ch = HDR_CMN(p); assert(initialized()); if(ch->prev_hop_ == ipaddr) { // I hate all uses of prev_hop, but the only other way to // do this test is by checking for a nonNULL handler (like // mac-801_11.cc does), which would // require changing tora to send out pkts with a non 0 hndler // -dam recv_outgoing(p); } else { recv_incoming(p); }}voidimepAgent::recv_outgoing(Packet *p){ struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ip = HDR_IP(p); if(DATA_PACKET(ch->ptype())) { imep_output(p); return; } if(ip->daddr() != (nsaddr_t) IP_BROADCAST) { fprintf(stderr, "IP dst is unicast - not encapsulating\n"); imep_output(p); return; } assert(ch->ptype() == PT_TORA); // XXX: for debugging purposes - IMEP supports other object types objectQueue.enque(p); // this queue is a queue of "packets" passed down from the // upper layer routing protocols that IMEP will buffer and try // to aggregate before transmitting. Although these are valid // packets, they must not be transmitted before encaspulating // them in an IMEP packet to ensure reliability. double send_delay = MIN_TRANSMIT_WAIT_TIME_HIGHP + ((MAX_TRANSMIT_WAIT_TIME_HIGHP - MIN_TRANSMIT_WAIT_TIME_HIGHP) * Random::uniform()); if (controlTimer.busy() == 0) { controlTimer.start(send_delay); } else if (controlTimer.timeLeft() > send_delay) { controlTimer.cancel(); controlTimer.start(send_delay); }}voidimepAgent::recv_incoming(Packet *p){ struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); struct hdr_imep *im = HDR_IMEP(p); if(DATA_PACKET(ch->ptype())) { imep_input(p); return; } // if it's a data packet, the ip->src could be from far away, // so we can't use it for link indications. If we RARPd the // MAC source addr, we could use that... imepSetLinkInStatus(ih->saddr()); // XXX: this could be done at the MAC layer. In fact, I will // augment the IEEE 802.11 layer so that the receipt of an // ACK confirms bidirectional status. -josh // hasn't actually be done. seems unlikely to be of help, and is // fairly hard to do. -dam 8/19/98 assert(ch->ptype() == PT_IMEP); assert(im->imep_version == IMEP_VERSION); if(im->imep_block_flags == 0) { imep_beacon_input(p); Packet::free(p); return; } if(im->imep_block_flags & BLOCK_FLAG_ACK) imep_ack_input(p); if(im->imep_block_flags & BLOCK_FLAG_HELLO) imep_hello_input(p); if(im->imep_block_flags & BLOCK_FLAG_OBJECT) { imep_object_input(p); // each upper layer object will be decapsulated and // placed into its own packet before being passed // to the upper layer. This provides total transparency // to the upper layer. } Packet::free(p);}voidimepAgent::imep_beacon_input(Packet *p){ struct hdr_ip *ip = HDR_IP(p); sendHello(ip->saddr());}// If there is an ACK for us we need to (1) removed the sender// of the ACK from the "ack list", and we need to update the// status of this neighbor to "BIDIRECTIONAL".voidimepAgent::imep_ack_input(Packet *p){ struct hdr_ip *ih = HDR_IP(p); struct imep_ack_block *ab = findAckBlock(p); struct imep_ack *ack; assert(ab); ack = (struct imep_ack*) (ab + 1); // According to the IMEP specs, the ACK block (if it exists) // immediately follows the 3-byte IMEP header. for(int i = 0; i < ab->ab_num_acks; i++, ack++) { if(INT32_T(ack->ack_ipaddr) == ipaddr) { Packet *p0 = findObjectSequence(ack->ack_seqno); if (NULL == p0) { if(verbose) trace("T %.9f _%d_ %d acks seq %d : no obj" " block", CURRENT_TIME, ipaddr, ih->saddr(), ack->ack_seqno); stats.num_unexpected_acks++; continue; } removeObjectResponse(p0, ih->saddr()); imepSetLinkBiStatus(ih->saddr()); } }}voidimepAgent::imep_hello_input(Packet *p){ struct hdr_ip *ip = HDR_IP(p); struct imep_hello_block *hb = findHelloBlock(p); struct imep_hello *hello; assert(hb); hello = (struct imep_hello*) (hb + 1); for(int i = 0; i < hb->hb_num_hellos; i++, hello++) { if(INT32_T(hello->hello_ipaddr) == ipaddr) { imepSetLinkBiStatus(ip->saddr()); break; } }}voidimepAgent::imep_object_input(Packet *p){ struct imep_object_block *ob; // First, send an ack for the object imep_ack_object(p); // now see what to do with the object ob = findObjectBlock(p); assert(ob); struct hdr_ip *iph = HDR_IP(p); imepLink *l = findLink(iph->saddr()); assert(l); // if we have an object, a link entry should already exist if (!l->lastSeqValid()) { // first object we've heard from this node l->lastSeqValid() = 1; l->lastSeq() = ob->ob_sequence - 1; if (verbose) trace("T %.9f _d_ first object from neighbor %d seq %d", CURRENT_TIME, ipaddr, iph->src().addr_, ob->ob_sequence); } // This calc requires sequence number SEQ_GT() semantics // Life will be very bad if this calc isn't actually done in // a register the size of the sequence number space int8_t reg = (int8_t) ob->ob_sequence - (int8_t) l->lastSeq(); if(reg <= 0) { // already passed this pkt up to ULP or declared it a permenant // hole if (verbose) trace("T %.9f _%d_ from %d ignored seq %d (already heard)", CURRENT_TIME, ipaddr, iph->src().addr_, ob->ob_sequence); stats.num_out_of_window_objs++; return; } if (verbose && reg > 1) { // found a hole in the sequence number space... trace("T %.9f _%d_ inorder - src %d seq %d out of order (%d expected)", CURRENT_TIME, ipaddr, iph->src().addr_, ob->ob_sequence, l->lastSeq()+1); } if (1 == reg) { // ``fast path'' // got the expected next seq num if (verbose) trace("T %.9f _%d_ inorder - fastpath src %d seq %d (delivering)", CURRENT_TIME, ipaddr, HDR_IP(p)->src().addr_, ob->ob_sequence); stats.num_in_order_objs++; imep_object_process(p); assert((u_int8_t)(l->lastSeq() + 1) == ob->ob_sequence); l->lastSeq() = ob->ob_sequence; } else { // put this packet on the resequencing queue scheduleIncoming(p->copy(), ob->ob_sequence); stats.num_out_of_order_objs++; } // now deliver as many in-sequence packets to ULP as possible Packet *p0; while((p0 = incomingQ.getPacket(iph->saddr(), l->lastSeq() + 1))) { stats.num_recvd_from_queue++; if (verbose) trace("T %.9f _%d_ inorder - src %d seq %d (delivering)", CURRENT_TIME, ipaddr, HDR_IP(p0)->src().addr_, l->lastSeq() + 1); l->lastSeq() += 1; imep_object_process(p0); Packet::free(p0); }}voidimepAgent::imep_object_process(Packet *p) // hand the conents of any object in the pkt to the respective ULP{ struct imep_object_block *ob; struct imep_object *object; int i; stats.num_object_pkts_recvd++; ob = findObjectBlock(p); assert(ob); assert(ob->ob_protocol_type == PROTO_TORA); // XXX: more general later object = (struct imep_object*) (ob + 1); for(i = 0; i < ob->ob_num_objects; i++) { Packet *p0 = p->copy(); assert(object->o_length > 0); // sanity check toraCreateHeader(p0, ((char*) object) + sizeof(struct imep_object), object->o_length); imep_input(p0); object = (struct imep_object*) ((char*) object + sizeof(struct imep_object) + object->o_length); }}voidimepAgent::imep_ack_object(Packet *p) // send an ack for the object in p, if any{ struct hdr_ip *iph = HDR_IP(p); struct imep_object_block *ob; struct imep_object *object; int i; ob = findObjectBlock(p); if (!ob) return; if (0 == ob->ob_num_responses) return; if (31 == ob->ob_num_responses) { // a ``broadcast'' response list to which everyone replies sendAck(iph->saddr(), ob->ob_sequence); return; } object = (struct imep_object*) (ob + 1); // walk the objects to find the response list for(i = 0; i < ob->ob_num_objects; i++) { object = (struct imep_object*) ((char*) object + sizeof(struct imep_object) + object->o_length); } struct imep_response *r = (struct imep_response*) object; for (i = 0; i < ob->ob_num_responses; i++) { if (INT32_T(r->resp_ipaddr) == ipaddr) { sendAck(iph->saddr(), ob->ob_sequence); break; } r = r + 1; }}// ======================================================================// ======================================================================// Routines by which packets leave the IMEP objectvoidimepAgent::imep_input(Packet *p){ recvtarget_->recv(p, (Handler*) 0);}voidimepAgent::imep_output(Packet *p){ struct hdr_cmn *ch = HDR_CMN(p); if(imep_use_mac_callback) { ch->xmit_failure_ = imep_failed_callback; ch->xmit_failure_data_ = (void*) this; } else { ch->xmit_failure_ = 0; ch->xmit_failure_data_ = 0; } ch->xmit_reason_ = 0; sendtarget_->recv(p, (Handler*) 0);}// ======================================================================// ======================================================================// Debugging routinesvoidimepAgent::imep_dump_header(Packet *p){ struct hdr_imep *im = HDR_IMEP(p); fprintf(stderr, "imep_version: 0x%x\n", im->imep_version); fprintf(stderr, "imep_block_flags: 0x%x\n", im->imep_block_flags); fprintf(stderr, "imep_length: 0x%04x\n", U_INT16_T(im->imep_length)); Packet::dump_header(p, off_IMEP_, 64);}voidimepAgent::log_neighbor_list(){ imepLink *l; int offset = 0; if(! verbose ) return; sprintf(logtarget_->buffer(), "T %.9f _%d_ neighbors: ", CURRENT_TIME, ipaddr); for(l = imepLinkHead.lh_first; l; l = l->link.le_next) { offset = strlen(logtarget_->buffer()); sprintf(logtarget_->buffer() + offset, "%d%c ", l->index(), l->status() == LINK_BI ? '+' : (l->status() == LINK_IN ? '-' : (l->status() == LINK_OUT ? '|' : 'X'))); } logtarget_->dump();}voidimepAgent::trace(char* fmt, ...){ va_list ap; if (!logtarget_) return; va_start(ap, fmt); vsprintf(logtarget_->buffer(), fmt, ap); logtarget_->dump(); va_end(ap);}char *imepAgent::dumpResponseList(Packet *p){ static char buf[512]; char *ptr = buf; struct imep_object_block *ob = findObjectBlock(p); struct imep_response *r = findResponseList(p); struct imep_response *r0; int i; for(i = 0, r0 = r; i < ob->ob_num_responses; i++, r0++) { ptr += (int)sprintf(ptr,"%d ", INT32_T(r0->resp_ipaddr)); } return buf;}voidimepAgent::Terminate(){ trace("IL %.9f _%d_ Add-Adj: %d New-Neigh: %d Del-Neigh1: %d Del-Neigh2: %d Del-Neigh3: %d", CURRENT_TIME, ipaddr, stats.new_in_adjacency, stats.new_neighbor , stats.delete_neighbor1 , stats.delete_neighbor2, stats.delete_neighbor3); trace("IL %.9f _%d_ Created QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr, stats.qry_objs_created , stats.upd_objs_created , stats.clr_objs_created); trace("IL %.9f _%d_ Received QRY: %d UPD: %d CLR: %d",CURRENT_TIME, ipaddr, stats.qry_objs_recvd , stats.upd_objs_recvd , stats.clr_objs_recvd); trace("IL %.9f _%d_ Total-Obj-Created: %d Obj-Pkt-Created: %d Obj-Pkt-Recvd: %d", CURRENT_TIME, ipaddr, stats.num_objects_created , stats.num_object_pkts_created , stats.num_object_pkts_recvd); trace("IL %.9f _%d_ Rexmit Pkts: %d Acked: %d Retired: %d Rexmits: %d", CURRENT_TIME, ipaddr, stats.num_rexmitable_pkts , stats.num_rexmitable_fully_acked , stats.num_rexmitable_retired , stats.num_rexmits); trace("IL %.9f _%d_ Sum-Response-List-Size Created: %d Retired: %d", CURRENT_TIME, ipaddr, stats.sum_response_list_sz , stats.sum_rexmitable_retired_response_sz); trace("IL %.9f _%d_ Holes Created: %d Retired: %d ReSeqQ-Drops: %d ReSeqQ-Recvd: %d", CURRENT_TIME, ipaddr, stats.num_holes_created , stats.num_holes_retired , stats.num_reseqq_drops, stats.num_recvd_from_queue); trace("IL %.9f _%d_ Unexpected-Acks: %d Out-Win-Obj: %d Out-Order-Obj: %d In-Order-Obj: %d", CURRENT_TIME, ipaddr, stats.num_unexpected_acks , stats.num_out_of_window_objs , stats.num_out_of_order_objs , stats.num_in_order_objs);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -