00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
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
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;
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 {
00261
00262
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
00283
00284
00285
00286
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
00310 ob->ob_protocol_type = PROTO_TORA;
00311 ob->ob_num_responses = 0;
00312
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 {
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 {
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
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 {
00388
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