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.6 2005/08/28 23:23:03 tomh 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 imep_object_block *ob;
00139     struct imep_object *object;
00140 
00141     assert(HDR_IMEP (p)->imep_version == IMEP_VERSION);
00142 
00143     if((ob = findObjectBlock(p)) == 0)
00144         return 0;
00145 
00146     if(ob->ob_num_responses <= 0)
00147         return 0;
00148 
00149     object = (struct imep_object*) (ob + 1);
00150     for(int i = 0; i < ob->ob_num_objects; i++) {
00151         object = (struct imep_object*) ((char*) object + 
00152               sizeof(struct imep_object) + object->o_length);
00153     }
00154 
00155     return (struct imep_response*) object;
00156 }
00157 
00158 // ======================================================================
00159 // ======================================================================
00160 
00161 void
00162 imepAgent::aggregateAckBlock(Packet *p)
00163 {
00164     struct hdr_cmn *ch = HDR_CMN(p);
00165     struct hdr_imep *im = HDR_IMEP(p);
00166     struct imep_ack_block *ab = (struct imep_ack_block*) (im + 1);
00167     struct imep_ack *ack = (struct imep_ack*) (ab + 1);
00168     int num_acks = ackQueue.length();
00169 
00170     if(num_acks == 0) return;
00171 
00172     ch->size() += sizeof(struct imep_ack_block);
00173     U_INT16_T(im->imep_length) += sizeof(struct imep_ack_block);
00174     im->imep_block_flags |= BLOCK_FLAG_ACK;
00175 
00176     ab->ab_num_acks = 0;
00177 
00178     for(int i = 0; i < num_acks; i++) {
00179 
00180             if (U_INT16_T(im->imep_length) + sizeof(struct imep_ack)
00181             > IMEP_HDR_LEN) break;
00182 
00183         Packet *p0 = ackQueue.deque();
00184         assert(p0);
00185 
00186         struct imep_ack_block *ab0 = findAckBlock(p0);
00187         assert(ab0);
00188 
00189         struct imep_ack *ack0 = (struct imep_ack*) (ab0 + 1);
00190 
00191         ack->ack_seqno = ack0->ack_seqno;
00192         U_INT32_T(ack->ack_ipaddr) = U_INT32_T(ack0->ack_ipaddr);
00193 
00194         if (verbose) trace("T %0.9f _%d_ ack   %d:%d",
00195                    CURRENT_TIME, ipaddr, 
00196                    U_INT32_T(ack->ack_ipaddr),
00197                    ack->ack_seqno);
00198 
00199         ch->size() += sizeof(struct imep_ack);
00200         U_INT16_T(im->imep_length) += sizeof(struct imep_ack);
00201         ab->ab_num_acks++;
00202         ack++;
00203 
00204         Packet::free(p0);
00205     }
00206     assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00207 }
00208 
00209 void
00210 imepAgent::aggregateHelloBlock(Packet *p)
00211 {
00212     struct hdr_cmn *ch = HDR_CMN(p);
00213     struct hdr_imep *im = HDR_IMEP(p);
00214     struct imep_hello_block *hb;
00215     struct imep_hello *hello;
00216     int num_hellos = helloQueue.length();
00217     int inserted_hellos = 0;
00218 
00219     if (num_hellos == 0) return;
00220     if (U_INT16_T(im->imep_length) + sizeof(struct imep_hello_block)
00221         + sizeof(struct imep_hello) > IMEP_HDR_LEN) return;
00222 
00223     hb = (struct imep_hello_block*)
00224         (((char*) im) + U_INT16_T(im->imep_length));
00225     hello = (struct imep_hello *) (hb + 1);
00226 
00227     ch->size() += sizeof(struct imep_hello_block);
00228     U_INT16_T(im->imep_length) += sizeof(struct imep_hello_block);
00229 
00230     for(int i = 0; i < num_hellos; i++) {
00231 
00232         if ( U_INT16_T(im->imep_length) + sizeof(struct imep_hello)
00233              > IMEP_HDR_LEN ) break; // no more room
00234 
00235         Packet *p0 = helloQueue.deque();
00236         assert(p0);
00237 
00238         struct imep_hello_block *hb0 = findHelloBlock(p0);
00239         assert(hb0);
00240 
00241         struct imep_hello *hello0 = (struct imep_hello*) (hb0 + 1);
00242 
00243         imepLink *l = findLink(U_INT32_T(hello0->hello_ipaddr));
00244 
00245         if (l && CURRENT_TIME != l->lastEcho())
00246           {
00247             if (verbose) trace("T %0.9f _%d_ hello %d",
00248                        CURRENT_TIME, ipaddr, 
00249                        U_INT32_T(hello0->hello_ipaddr));
00250             U_INT32_T(hello->hello_ipaddr) =
00251               U_INT32_T(hello0->hello_ipaddr);
00252             hello++;
00253             l->lastEcho() = CURRENT_TIME;
00254 
00255             inserted_hellos++;
00256             ch->size() += sizeof(struct imep_hello);
00257             U_INT16_T(im->imep_length) += sizeof(struct imep_hello);
00258           }
00259         else 
00260           { // this dest is already in this hello block, 
00261             // or it was removed from our adj list since the 
00262             // Hello was scheduled for it, so skip the dest
00263           }
00264 
00265         Packet::free(p0);
00266     }
00267 
00268     if (0 == inserted_hellos) 
00269       {
00270         ch->size() -= sizeof(struct imep_hello_block);
00271         U_INT16_T(im->imep_length) -= sizeof(struct imep_hello_block);
00272         return;
00273       }
00274 
00275     hb->hb_num_hellos = inserted_hellos;
00276     im->imep_block_flags |= BLOCK_FLAG_HELLO;
00277 
00278     assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00279 }
00280 
00281 
00282 // XXX: Objects generatd by TORA or other upper layer protocols
00283 // don't contain a "response list".  Since, there is only one "response list"
00284 // for potentially many objects, we generate the response list when
00285 // the packet is sent.  I can't think of a case where the response
00286 // list would NOT be "all of my neighbors."
00287 void
00288 imepAgent::aggregateObjectBlock(Packet *p)
00289 {
00290     struct hdr_cmn *ch = HDR_CMN(p);
00291     struct hdr_imep *im = HDR_IMEP(p);
00292     struct imep_object_block *ob;
00293     struct imep_object *object;
00294     int num_objects = objectQueue.length();
00295     int response_list_len;
00296     int num_objects_inserted;
00297 
00298     if(num_objects == 0) return;
00299     if (U_INT16_T(im->imep_length) >= IMEP_HDR_LEN) return;
00300 
00301     ob = (struct imep_object_block*)
00302         ((char*) im + U_INT16_T(im->imep_length));
00303     U_INT16_T(im->imep_length) += sizeof(struct imep_object_block);
00304     ch->size() += sizeof(struct imep_object_block);
00305 
00306     object = (struct imep_object*) (ob + 1);    
00307 
00308     ob->ob_sequence = 0;
00309     // initialized when the "response list" is created.
00310     ob->ob_protocol_type = PROTO_TORA; // XXX
00311     ob->ob_num_responses = 0;
00312     // initialized when the "response list" is created.
00313 
00314     response_list_len = getResponseListSize();
00315 
00316     for(num_objects_inserted = 0; 
00317         num_objects_inserted < num_objects; 
00318         num_objects_inserted++) {
00319 
00320         Packet *p0 = objectQueue.deque();
00321         assert(p0);
00322 
00323         struct hdr_cmn *ch0 = HDR_CMN(p0);
00324         struct hdr_tora *t = HDR_TORA(p0);
00325 
00326         int obj_length = toraHeaderLength(t);
00327         int new_len = U_INT16_T(im->imep_length) 
00328           + sizeof(struct imep_object) + obj_length 
00329           + response_list_len;
00330         if (new_len > IMEP_HDR_LEN)
00331           { // object won't fit, stop now
00332             objectQueue.enqueHead(p0);
00333             break;
00334           }
00335 
00336         switch(ch0->ptype()) {
00337 
00338         case PT_TORA:
00339                 toraExtractHeader(p0, ((char*) object) 
00340                           + sizeof(struct imep_object));
00341             break;
00342 
00343         default:
00344             fprintf(stderr, "Invalid Packet Type  %d\n",
00345                 ch0->ptype());
00346             abort();
00347         }
00348 
00349         ch->size() += sizeof(struct imep_object) + obj_length;
00350 
00351         U_INT16_T(im->imep_length) +=
00352             sizeof(struct imep_object) + obj_length;
00353 
00354         object->o_length = obj_length;
00355 
00356         object = (struct imep_object*) ((char*) object + 
00357                sizeof(struct imep_object) + obj_length);
00358 
00359         Packet::free(p0);
00360     }
00361 
00362     assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
00363 
00364     if (0 == num_objects_inserted)
00365       { // remove the object block hdr we just worked so hard to put in
00366         U_INT16_T(im->imep_length) -= sizeof(struct imep_object_block);
00367         ch->size() -= sizeof(struct imep_object_block);
00368         return;
00369       }
00370 
00371     im->imep_block_flags |= BLOCK_FLAG_OBJECT;
00372     ob->ob_num_objects = num_objects_inserted;
00373     assert(ob->ob_protocol_type == PROTO_TORA);
00374 
00375     // add the response list
00376     createResponseList(p);
00377 
00378     stats.num_objects_created += num_objects_inserted;
00379     stats.num_object_pkts_created++;
00380     stats.sum_response_list_sz += ob->ob_num_responses;
00381     
00382     if (verbose) 
00383       trace("T %.9f _%d_ # obj %d seq %d #resp %d RL %s", CURRENT_TIME, ipaddr,
00384         ob->ob_num_objects, ob->ob_sequence, ob->ob_num_responses, dumpResponseList(p));
00385 
00386     if (ob->ob_num_responses > 0)
00387       { // now make a packet to save on the rexmit queue with only the
00388         // object block and response list in it
00389         Packet *sp = p->copy();
00390         struct hdr_imep *sim = HDR_IMEP(sp);
00391         struct hdr_cmn *sch = HDR_CMN(sp);
00392         sim->imep_block_flags &= ~(BLOCK_FLAG_ACK | BLOCK_FLAG_HELLO);
00393         int objrep_len = U_INT16_T(im->imep_length) 
00394           - (int) ((char*) ob - (char*) im);
00395         bcopy(ob, (char *)(sim + 1), objrep_len);
00396         U_INT16_T(sim->imep_length) = sizeof(struct hdr_imep) + objrep_len;
00397         sch->size() = IP_HDR_LEN  + sizeof(struct hdr_imep) + objrep_len;
00398         stats.num_rexmitable_pkts++;
00399 
00400         scheduleReXmit(sp);
00401       }
00402 }
00403 
00404 // ======================================================================
00405 // ======================================================================
00406 
00407 int 
00408 imepAgent::getResponseListSize()
00409 {
00410   int size = 0;
00411   for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
00412 
00413     if (l->status() != LINK_BI) continue;
00414     size += sizeof(struct imep_response);
00415   }
00416   return size;
00417 }
00418 
00419 void
00420 imepAgent::createResponseList(Packet *p)
00421 {
00422     struct hdr_cmn *ch = HDR_CMN(p);
00423     struct hdr_imep *im = HDR_IMEP(p);
00424     struct imep_object_block *ob;
00425 
00426     if((im->imep_block_flags & BLOCK_FLAG_OBJECT) == 0)
00427         return;
00428 
00429     ob = findObjectBlock(p);
00430     assert(ob);
00431 
00432     ob->ob_sequence = nextSequence();
00433 
00434     struct imep_response *r = (struct imep_response*)
00435         ((char*) im + U_INT16_T(im->imep_length));
00436 
00437     for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
00438 
00439             if (l->status() != LINK_BI) continue;
00440 
00441         ch->size() += sizeof(struct imep_response);
00442         U_INT16_T(im->imep_length) += sizeof(struct imep_response);
00443         ob->ob_num_responses += 1;
00444 
00445         INT32_T(r->resp_ipaddr) = l->index();
00446         r++;
00447     }
00448 }
00449 

Generated on Tue Mar 6 16:47:46 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6