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 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;
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 {
00262
00263
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
00284
00285
00286
00287
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
00311 ob->ob_protocol_type = PROTO_TORA;
00312 ob->ob_num_responses = 0;
00313
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 {
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 {
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
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 {
00389
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