Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

imep_util.cc

Go to the documentation of this file.
00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 /*
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Computer Systems
00017  *      Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  */
00034 /* Ported from CMU/Monarch's code*/
00035 
00036 /*
00037   imep_util.cc
00038   $Id: imep_util.cc,v 1.3 2000/09/01 03:04:10 haoboy Exp $
00039   */
00040 
00041 #include "packet.h"
00042 #include "tora/tora_packet.h"
00043 #include "imep/imep.h"
00044 
00045 #define CURRENT_TIME    Scheduler::instance().clock()
00046 
00047 static const int verbose = 0;
00048 
00049 // ======================================================================
00050 // Utility routines to manipulate IMEP packets.
00051 
00052 imep_ack_block*
00053 imepAgent::findAckBlock(Packet *p)
00054 {
00055         struct hdr_imep *im = HDR_IMEP(p);
00056         struct imep_ack_block *ab;
00057 
00058         assert(im->imep_version == IMEP_VERSION);
00059 
00060         if((im->imep_block_flags & BLOCK_FLAG_ACK) == 0)
00061                 return 0;
00062 
00063         ab = (struct imep_ack_block*) (im + 1);
00064 
00065         assert(ab->ab_num_acks > 0);
00066 
00067         return ab;
00068 }
00069 
00070 imep_hello_block*
00071 imepAgent::findHelloBlock(Packet *p)
00072 {
00073         struct hdr_imep *im = HDR_IMEP(p);
00074         struct imep_hello_block *hb;
00075 
00076         assert(im->imep_version == IMEP_VERSION);
00077 
00078         if((im->imep_block_flags & BLOCK_FLAG_HELLO) == 0)
00079                 return 0;
00080 
00081         if(im->imep_block_flags & BLOCK_FLAG_ACK) {
00082                 struct imep_ack_block *ab = findAckBlock(p);
00083                 struct imep_ack *ack = (struct imep_ack*) (ab + 1);
00084 
00085                 hb = (struct imep_hello_block*) (ack + ab->ab_num_acks);
00086         }
00087         else {
00088                 hb = (struct imep_hello_block*) (im + 1);
00089         }
00090 
00091         assert(hb->hb_num_hellos > 0);
00092 
00093         return hb;
00094 }
00095 
00096 imep_object_block*
00097 imepAgent::findObjectBlock(Packet *p)
00098 {
00099         struct hdr_imep *im = HDR_IMEP(p);
00100         struct imep_ack_block *ab;
00101         struct imep_hello_block *hb;
00102         struct imep_object_block *ob;
00103         char *ptr;
00104 
00105         assert(im->imep_version == IMEP_VERSION);
00106 
00107         if((im->imep_block_flags & BLOCK_FLAG_OBJECT) == 0)
00108                 return 0;       
00109         
00110         ptr = (char *) (im + 1);
00111 
00112         if (im->imep_block_flags & BLOCK_FLAG_ACK) {
00113           ab = (struct imep_ack_block*) ptr;
00114           ptr += ab->ab_num_acks * sizeof(struct imep_ack)
00115             + sizeof(struct imep_ack_block);
00116           assert(ab->ab_num_acks > 0);
00117         }
00118         if (im->imep_block_flags & BLOCK_FLAG_HELLO) {
00119           hb = (struct imep_hello_block *) ptr;
00120           ptr += hb->hb_num_hellos * sizeof(struct imep_hello) 
00121             + sizeof(struct imep_hello_block);
00122           assert(hb->hb_num_hellos > 0);
00123         }
00124 
00125         ob = (struct imep_object_block*) ptr;
00126 
00127         assert(ob->ob_protocol_type == PROTO_TORA);
00128         // for debugging purposes only
00129 
00130         assert(ob->ob_num_objects > 0);
00131 
00132         return ob;
00133 }
00134 
00135 struct imep_response*
00136 imepAgent::findResponseList(Packet *p)
00137 {
00138         struct hdr_imep *im = HDR_IMEP(p);
00139         struct imep_object_block *ob;
00140         struct imep_object *object;
00141 
00142         assert(im->imep_version == IMEP_VERSION);
00143 
00144         if((ob = findObjectBlock(p)) == 0)
00145                 return 0;
00146 
00147         if(ob->ob_num_responses <= 0)
00148                 return 0;
00149 
00150         object = (struct imep_object*) (ob + 1);
00151         for(int i = 0; i < ob->ob_num_objects; i++) {
00152                 object = (struct imep_object*) ((char*) object + 
00153                           sizeof(struct imep_object) + object->o_length);
00154         }
00155 
00156         return (struct imep_response*) object;
00157 }
00158 
00159 // ======================================================================
00160 // ======================================================================
00161 
00162 void
00163 imepAgent::aggregateAckBlock(Packet *p)
00164 {
00165         struct hdr_cmn *ch = HDR_CMN(p);
00166         struct hdr_imep *im = HDR_IMEP(p);
00167         struct imep_ack_block *ab = (struct imep_ack_block*) (im + 1);
00168         struct imep_ack *ack = (struct imep_ack*) (ab + 1);
00169         int num_acks = ackQueue.length();
00170 
00171         if(num_acks == 0) return;
00172 
00173         ch->size() += sizeof(struct imep_ack_block);
00174         U_INT16_T(im->imep_length) += sizeof(struct imep_ack_block);
00175         im->imep_block_flags |= BLOCK_FLAG_ACK;
00176 
00177         ab->ab_num_acks = 0;
00178 
00179         for(int i = 0; i < num_acks; i++) {
00180 
00181                 if (U_INT16_T(im->imep_length) + sizeof(struct imep_ack)
00182                     > IMEP_HDR_LEN) break;
00183 
00184                 Packet *p0 = ackQueue.deque();
00185                 assert(p0);
00186 
00187                 struct imep_ack_block *ab0 = findAckBlock(p0);
00188                 assert(ab0);
00189 
00190                 struct imep_ack *ack0 = (struct imep_ack*) (ab0 + 1);
00191 
00192                 ack->ack_seqno = ack0->ack_seqno;
00193                 U_INT32_T(ack->ack_ipaddr) = U_INT32_T(ack0->ack_ipaddr);
00194 
00195                 if (verbose) trace("T %0.9f _%d_ ack   %d:%d",
00196                                    CURRENT_TIME, ipaddr, 
00197                                    U_INT32_T(ack->ack_ipaddr),
00198                                    ack->ack_seqno);
00199 
00200                 ch->size() += sizeof(struct imep_ack);
00201                 U_INT16_T(im->imep_length) += sizeof(struct imep_ack);
00202                 ab->ab_num_acks++;
00203                 ack++;
00204 
00205                 Packet::free(p0);
00206         }
00207         assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00208 }
00209 
00210 void
00211 imepAgent::aggregateHelloBlock(Packet *p)
00212 {
00213         struct hdr_cmn *ch = HDR_CMN(p);
00214         struct hdr_imep *im = HDR_IMEP(p);
00215         struct imep_hello_block *hb;
00216         struct imep_hello *hello;
00217         int num_hellos = helloQueue.length();
00218         int inserted_hellos = 0;
00219 
00220         if (num_hellos == 0) return;
00221         if (U_INT16_T(im->imep_length) + sizeof(struct imep_hello_block)
00222             + sizeof(struct imep_hello) > IMEP_HDR_LEN) return;
00223 
00224         hb = (struct imep_hello_block*)
00225                 (((char*) im) + U_INT16_T(im->imep_length));
00226         hello = (struct imep_hello *) (hb + 1);
00227 
00228         ch->size() += sizeof(struct imep_hello_block);
00229         U_INT16_T(im->imep_length) += sizeof(struct imep_hello_block);
00230 
00231         for(int i = 0; i < num_hellos; i++) {
00232 
00233                 if ( U_INT16_T(im->imep_length) + sizeof(struct imep_hello)
00234                      > IMEP_HDR_LEN ) break; // no more room
00235 
00236                 Packet *p0 = helloQueue.deque();
00237                 assert(p0);
00238 
00239                 struct imep_hello_block *hb0 = findHelloBlock(p0);
00240                 assert(hb0);
00241 
00242                 struct imep_hello *hello0 = (struct imep_hello*) (hb0 + 1);
00243 
00244                 imepLink *l = findLink(U_INT32_T(hello0->hello_ipaddr));
00245 
00246                 if (l && CURRENT_TIME != l->lastEcho())
00247                   {
00248                     if (verbose) trace("T %0.9f _%d_ hello %d",
00249                                        CURRENT_TIME, ipaddr, 
00250                                        U_INT32_T(hello0->hello_ipaddr));
00251                     U_INT32_T(hello->hello_ipaddr) =
00252                       U_INT32_T(hello0->hello_ipaddr);
00253                     hello++;
00254                     l->lastEcho() = CURRENT_TIME;
00255 
00256                     inserted_hellos++;
00257                     ch->size() += sizeof(struct imep_hello);
00258                     U_INT16_T(im->imep_length) += sizeof(struct imep_hello);
00259                   }
00260                 else 
00261                   { // this dest is already in this hello block, 
00262                     // or it was removed from our adj list since the 
00263                     // Hello was scheduled for it, so skip the dest
00264                   }
00265 
00266                 Packet::free(p0);
00267         }
00268 
00269         if (0 == inserted_hellos) 
00270           {
00271             ch->size() -= sizeof(struct imep_hello_block);
00272             U_INT16_T(im->imep_length) -= sizeof(struct imep_hello_block);
00273             return;
00274           }
00275 
00276         hb->hb_num_hellos = inserted_hellos;
00277         im->imep_block_flags |= BLOCK_FLAG_HELLO;
00278 
00279         assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00280 }
00281 
00282 
00283 // XXX: Objects generatd by TORA or other upper layer protocols
00284 // don't contain a "response list".  Since, there is only one "response list"
00285 // for potentially many objects, we generate the response list when
00286 // the packet is sent.  I can't think of a case where the response
00287 // list would NOT be "all of my neighbors."
00288 void
00289 imepAgent::aggregateObjectBlock(Packet *p)
00290 {
00291         struct hdr_cmn *ch = HDR_CMN(p);
00292         struct hdr_imep *im = HDR_IMEP(p);
00293         struct imep_object_block *ob;
00294         struct imep_object *object;
00295         int num_objects = objectQueue.length();
00296         int response_list_len;
00297         int num_objects_inserted;
00298 
00299         if(num_objects == 0) return;
00300         if (U_INT16_T(im->imep_length) >= IMEP_HDR_LEN) return;
00301 
00302         ob = (struct imep_object_block*)
00303                 ((char*) im + U_INT16_T(im->imep_length));
00304         U_INT16_T(im->imep_length) += sizeof(struct imep_object_block);
00305         ch->size() += sizeof(struct imep_object_block);
00306 
00307         object = (struct imep_object*) (ob + 1);        
00308 
00309         ob->ob_sequence = 0;
00310         // initialized when the "response list" is created.
00311         ob->ob_protocol_type = PROTO_TORA; // XXX
00312         ob->ob_num_responses = 0;
00313         // initialized when the "response list" is created.
00314 
00315         response_list_len = getResponseListSize();
00316 
00317         for(num_objects_inserted = 0; 
00318             num_objects_inserted < num_objects; 
00319             num_objects_inserted++) {
00320 
00321                 Packet *p0 = objectQueue.deque();
00322                 assert(p0);
00323 
00324                 struct hdr_cmn *ch0 = HDR_CMN(p0);
00325                 struct hdr_tora *t = HDR_TORA(p0);
00326 
00327                 int obj_length = toraHeaderLength(t);
00328                 int new_len = U_INT16_T(im->imep_length) 
00329                   + sizeof(struct imep_object) + obj_length 
00330                   + response_list_len;
00331                 if (new_len > IMEP_HDR_LEN)
00332                   { // object won't fit, stop now
00333                     objectQueue.enqueHead(p0);
00334                     break;
00335                   }
00336 
00337                 switch(ch0->ptype()) {
00338 
00339                 case PT_TORA:
00340                         toraExtractHeader(p0, ((char*) object) 
00341                                               + sizeof(struct imep_object));
00342                         break;
00343 
00344                 default:
00345                         fprintf(stderr, "Invalid Packet Type  %d\n",
00346                                 ch0->ptype());
00347                         abort();
00348                 }
00349 
00350                 ch->size() += sizeof(struct imep_object) + obj_length;
00351 
00352                 U_INT16_T(im->imep_length) +=
00353                         sizeof(struct imep_object) + obj_length;
00354 
00355                 object->o_length = obj_length;
00356 
00357                 object = (struct imep_object*) ((char*) object + 
00358                            sizeof(struct imep_object) + obj_length);
00359 
00360                 Packet::free(p0);
00361         }
00362 
00363         assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00364 
00365         if (0 == num_objects_inserted)
00366           { // remove the object block hdr we just worked so hard to put in
00367             U_INT16_T(im->imep_length) -= sizeof(struct imep_object_block);
00368             ch->size() -= sizeof(struct imep_object_block);
00369             return;
00370           }
00371 
00372         im->imep_block_flags |= BLOCK_FLAG_OBJECT;
00373         ob->ob_num_objects = num_objects_inserted;
00374         assert(ob->ob_protocol_type == PROTO_TORA);
00375 
00376         // add the response list
00377         createResponseList(p);
00378 
00379         stats.num_objects_created += num_objects_inserted;
00380         stats.num_object_pkts_created++;
00381         stats.sum_response_list_sz += ob->ob_num_responses;
00382         
00383         if (verbose) 
00384           trace("T %.9f _%d_ # obj %d seq %d #resp %d RL %s", CURRENT_TIME, ipaddr,
00385                 ob->ob_num_objects, ob->ob_sequence, ob->ob_num_responses, dumpResponseList(p));
00386 
00387         if (ob->ob_num_responses > 0)
00388           { // now make a packet to save on the rexmit queue with only the
00389             // object block and response list in it
00390             Packet *sp = p->copy();
00391             struct hdr_imep *sim = HDR_IMEP(sp);
00392             struct hdr_cmn *sch = HDR_CMN(sp);
00393             sim->imep_block_flags &= ~(BLOCK_FLAG_ACK | BLOCK_FLAG_HELLO);
00394             int objrep_len = U_INT16_T(im->imep_length) 
00395               - (int) ((char*) ob - (char*) im);
00396             bcopy(ob, (char *)(sim + 1), objrep_len);
00397             U_INT16_T(sim->imep_length) = sizeof(struct hdr_imep) + objrep_len;
00398             sch->size() = IP_HDR_LEN  + sizeof(struct hdr_imep) + objrep_len;
00399             stats.num_rexmitable_pkts++;
00400 
00401             scheduleReXmit(sp);
00402           }
00403 }
00404 
00405 // ======================================================================
00406 // ======================================================================
00407 
00408 int 
00409 imepAgent::getResponseListSize()
00410 {
00411   int size = 0;
00412   for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
00413 
00414     if (l->status() != LINK_BI) continue;
00415     size += sizeof(struct imep_response);
00416   }
00417   return size;
00418 }
00419 
00420 void
00421 imepAgent::createResponseList(Packet *p)
00422 {
00423         struct hdr_cmn *ch = HDR_CMN(p);
00424         struct hdr_imep *im = HDR_IMEP(p);
00425         struct imep_object_block *ob;
00426 
00427         if((im->imep_block_flags & BLOCK_FLAG_OBJECT) == 0)
00428                 return;
00429 
00430         ob = findObjectBlock(p);
00431         assert(ob);
00432 
00433         ob->ob_sequence = nextSequence();
00434 
00435         struct imep_response *r = (struct imep_response*)
00436                 ((char*) im + U_INT16_T(im->imep_length));
00437 
00438         for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
00439 
00440                 if (l->status() != LINK_BI) continue;
00441 
00442                 ch->size() += sizeof(struct imep_response);
00443                 U_INT16_T(im->imep_length) += sizeof(struct imep_response);
00444                 ob->ob_num_responses += 1;
00445 
00446                 INT32_T(r->resp_ipaddr) = l->index();
00447                 r++;
00448         }
00449 }
00450 

Generated on Tue Apr 20 12:14:20 2004 for NS2.26SourcesOriginal by doxygen 1.3.3