imep_util.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. /*
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  *      This product includes software developed by the Computer Systems
  17.  *      Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  */
  34. /* Ported from CMU/Monarch's code*/
  35. /*
  36.   imep_util.cc
  37.   $Id: imep_util.cc,v 1.7 2006/02/21 15:20:18 mahrenho Exp $
  38.   */
  39. #include "packet.h"
  40. #include "tora/tora_packet.h"
  41. #include "imep/imep.h"
  42. #define CURRENT_TIME Scheduler::instance().clock()
  43. static const int verbose = 0;
  44. // ======================================================================
  45. // Utility routines to manipulate IMEP packets.
  46. imep_ack_block*
  47. imepAgent::findAckBlock(Packet *p)
  48. {
  49. struct hdr_imep *im = HDR_IMEP(p);
  50. struct imep_ack_block *ab;
  51. assert(im->imep_version == IMEP_VERSION);
  52. if((im->imep_block_flags & BLOCK_FLAG_ACK) == 0)
  53. return 0;
  54. ab = (struct imep_ack_block*) (im + 1);
  55. assert(ab->ab_num_acks > 0);
  56. return ab;
  57. }
  58. imep_hello_block*
  59. imepAgent::findHelloBlock(Packet *p)
  60. {
  61. struct hdr_imep *im = HDR_IMEP(p);
  62. struct imep_hello_block *hb;
  63. assert(im->imep_version == IMEP_VERSION);
  64. if((im->imep_block_flags & BLOCK_FLAG_HELLO) == 0)
  65. return 0;
  66. if(im->imep_block_flags & BLOCK_FLAG_ACK) {
  67. struct imep_ack_block *ab = findAckBlock(p);
  68. struct imep_ack *ack = (struct imep_ack*) (ab + 1);
  69. hb = (struct imep_hello_block*) (ack + ab->ab_num_acks);
  70. }
  71. else {
  72. hb = (struct imep_hello_block*) (im + 1);
  73. }
  74. assert(hb->hb_num_hellos > 0);
  75. return hb;
  76. }
  77. imep_object_block*
  78. imepAgent::findObjectBlock(Packet *p)
  79. {
  80. struct hdr_imep *im = HDR_IMEP(p);
  81. struct imep_ack_block *ab;
  82. struct imep_hello_block *hb;
  83. struct imep_object_block *ob;
  84. char *ptr;
  85. assert(im->imep_version == IMEP_VERSION);
  86. if((im->imep_block_flags & BLOCK_FLAG_OBJECT) == 0)
  87. return 0;
  88. ptr = (char *) (im + 1);
  89. if (im->imep_block_flags & BLOCK_FLAG_ACK) {
  90.   ab = (struct imep_ack_block*) ptr;
  91.   ptr += ab->ab_num_acks * sizeof(struct imep_ack)
  92.     + sizeof(struct imep_ack_block);
  93.   assert(ab->ab_num_acks > 0);
  94. }
  95. if (im->imep_block_flags & BLOCK_FLAG_HELLO) {
  96.   hb = (struct imep_hello_block *) ptr;
  97.   ptr += hb->hb_num_hellos * sizeof(struct imep_hello) 
  98.     + sizeof(struct imep_hello_block);
  99.   assert(hb->hb_num_hellos > 0);
  100. }
  101. ob = (struct imep_object_block*) ptr;
  102. assert(ob->ob_protocol_type == PROTO_TORA);
  103. // for debugging purposes only
  104. assert(ob->ob_num_objects > 0);
  105. return ob;
  106. }
  107. struct imep_response*
  108. imepAgent::findResponseList(Packet *p)
  109. {
  110. struct imep_object_block *ob;
  111. struct imep_object *object;
  112. assert(HDR_IMEP (p)->imep_version == IMEP_VERSION);
  113. if((ob = findObjectBlock(p)) == 0)
  114. return 0;
  115. if(ob->ob_num_responses <= 0)
  116. return 0;
  117. object = (struct imep_object*) (ob + 1);
  118. for(int i = 0; i < ob->ob_num_objects; i++) {
  119. object = (struct imep_object*) ((char*) object + 
  120.    IMEP_OBJECT_SIZE + object->o_length);
  121. }
  122. return (struct imep_response*) object;
  123. }
  124. // ======================================================================
  125. // ======================================================================
  126. void
  127. imepAgent::aggregateAckBlock(Packet *p)
  128. {
  129. struct hdr_cmn *ch = HDR_CMN(p);
  130. struct hdr_imep *im = HDR_IMEP(p);
  131. struct imep_ack_block *ab = (struct imep_ack_block*) (im + 1);
  132. struct imep_ack *ack = (struct imep_ack*) (ab + 1);
  133. int num_acks = ackQueue.length();
  134. if(num_acks == 0) return;
  135. ch->size() += sizeof(struct imep_ack_block);
  136. U_INT16_T(im->imep_length) += sizeof(struct imep_ack_block);
  137. im->imep_block_flags |= BLOCK_FLAG_ACK;
  138. ab->ab_num_acks = 0;
  139. for(int i = 0; i < num_acks; i++) {
  140.         if (U_INT16_T(im->imep_length) + sizeof(struct imep_ack)
  141.     > IMEP_HDR_LEN) break;
  142. Packet *p0 = ackQueue.deque();
  143. assert(p0);
  144. struct imep_ack_block *ab0 = findAckBlock(p0);
  145. assert(ab0);
  146. struct imep_ack *ack0 = (struct imep_ack*) (ab0 + 1);
  147. ack->ack_seqno = ack0->ack_seqno;
  148. U_INT32_T(ack->ack_ipaddr) = U_INT32_T(ack0->ack_ipaddr);
  149. if (verbose) trace("T %0.9f _%d_ ack   %d:%d",
  150.    CURRENT_TIME, ipaddr, 
  151.    U_INT32_T(ack->ack_ipaddr),
  152.    ack->ack_seqno);
  153. ch->size() += sizeof(struct imep_ack);
  154. U_INT16_T(im->imep_length) += sizeof(struct imep_ack);
  155. ab->ab_num_acks++;
  156. ack++;
  157. Packet::free(p0);
  158. }
  159. assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
  160. }
  161. void
  162. imepAgent::aggregateHelloBlock(Packet *p)
  163. {
  164. struct hdr_cmn *ch = HDR_CMN(p);
  165. struct hdr_imep *im = HDR_IMEP(p);
  166. struct imep_hello_block *hb;
  167. struct imep_hello *hello;
  168. int num_hellos = helloQueue.length();
  169. int inserted_hellos = 0;
  170. if (num_hellos == 0) return;
  171. if (U_INT16_T(im->imep_length) + sizeof(struct imep_hello_block)
  172.     + sizeof(struct imep_hello) > IMEP_HDR_LEN) return;
  173. hb = (struct imep_hello_block*)
  174. (((char*) im) + U_INT16_T(im->imep_length));
  175. hello = (struct imep_hello *) (hb + 1);
  176. ch->size() += sizeof(struct imep_hello_block);
  177. U_INT16_T(im->imep_length) += sizeof(struct imep_hello_block);
  178. for(int i = 0; i < num_hellos; i++) {
  179. if ( U_INT16_T(im->imep_length) + sizeof(struct imep_hello)
  180.      > IMEP_HDR_LEN ) break; // no more room
  181. Packet *p0 = helloQueue.deque();
  182. assert(p0);
  183. struct imep_hello_block *hb0 = findHelloBlock(p0);
  184. assert(hb0);
  185. struct imep_hello *hello0 = (struct imep_hello*) (hb0 + 1);
  186. imepLink *l = findLink(U_INT32_T(hello0->hello_ipaddr));
  187. if (l && CURRENT_TIME != l->lastEcho())
  188.   {
  189.     if (verbose) trace("T %0.9f _%d_ hello %d",
  190.        CURRENT_TIME, ipaddr, 
  191.        U_INT32_T(hello0->hello_ipaddr));
  192.     U_INT32_T(hello->hello_ipaddr) =
  193.       U_INT32_T(hello0->hello_ipaddr);
  194.     hello++;
  195.     l->lastEcho() = CURRENT_TIME;
  196.     inserted_hellos++;
  197.     ch->size() += sizeof(struct imep_hello);
  198.     U_INT16_T(im->imep_length) += sizeof(struct imep_hello);
  199.   }
  200. else 
  201.   { // this dest is already in this hello block, 
  202.     // or it was removed from our adj list since the 
  203.     // Hello was scheduled for it, so skip the dest
  204.   }
  205. Packet::free(p0);
  206. }
  207. if (0 == inserted_hellos) 
  208.   {
  209.     ch->size() -= sizeof(struct imep_hello_block);
  210.     U_INT16_T(im->imep_length) -= sizeof(struct imep_hello_block);
  211.     return;
  212.   }
  213. hb->hb_num_hellos = inserted_hellos;
  214. im->imep_block_flags |= BLOCK_FLAG_HELLO;
  215. assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
  216. }
  217. // XXX: Objects generatd by TORA or other upper layer protocols
  218. // don't contain a "response list".  Since, there is only one "response list"
  219. // for potentially many objects, we generate the response list when
  220. // the packet is sent.  I can't think of a case where the response
  221. // list would NOT be "all of my neighbors."
  222. void
  223. imepAgent::aggregateObjectBlock(Packet *p)
  224. {
  225. struct hdr_cmn *ch = HDR_CMN(p);
  226. struct hdr_imep *im = HDR_IMEP(p);
  227. struct imep_object_block *ob;
  228. struct imep_object *object;
  229. int num_objects = objectQueue.length();
  230. int response_list_len;
  231. int num_objects_inserted;
  232. if(num_objects == 0) return;
  233. if (U_INT16_T(im->imep_length) >= IMEP_HDR_LEN) return;
  234. ob = (struct imep_object_block*)
  235. ((char*) im + U_INT16_T(im->imep_length));
  236. U_INT16_T(im->imep_length) += IMEP_OBJECT_BLOCK_SIZE;
  237. ch->size() += IMEP_OBJECT_BLOCK_SIZE;
  238. object = (struct imep_object*) (ob + 1);
  239. ob->ob_sequence = 0;
  240. // initialized when the "response list" is created.
  241. ob->ob_protocol_type = PROTO_TORA; // XXX
  242. ob->ob_num_responses = 0;
  243. // initialized when the "response list" is created.
  244. response_list_len = getResponseListSize();
  245. for(num_objects_inserted = 0; 
  246.     num_objects_inserted < num_objects; 
  247.     num_objects_inserted++) {
  248. Packet *p0 = objectQueue.deque();
  249. assert(p0);
  250. struct hdr_cmn *ch0 = HDR_CMN(p0);
  251. struct hdr_tora *t = HDR_TORA(p0);
  252. int obj_length = toraHeaderLength(t);
  253. int new_len = U_INT16_T(im->imep_length) 
  254.   + IMEP_OBJECT_SIZE + obj_length 
  255.   + response_list_len;
  256. if (new_len > IMEP_HDR_LEN)
  257.   { // object won't fit, stop now
  258.     objectQueue.enqueHead(p0);
  259.     break;
  260.   }
  261. switch(ch0->ptype()) {
  262. case PT_TORA:
  263.             toraExtractHeader(p0, ((char*) object) 
  264.   + IMEP_OBJECT_SIZE);
  265. break;
  266. default:
  267. fprintf(stderr, "Invalid Packet Type  %dn",
  268. ch0->ptype());
  269. abort();
  270. }
  271. ch->size() += IMEP_OBJECT_SIZE + obj_length;
  272. U_INT16_T(im->imep_length) +=
  273. IMEP_OBJECT_SIZE + obj_length;
  274. object->o_length = obj_length;
  275. object = (struct imep_object*) ((char*) object + 
  276.    IMEP_OBJECT_SIZE + obj_length);
  277. Packet::free(p0);
  278. }
  279. assert(U_INT16_T(im->imep_length) <= IMEP_HDR_LEN);
  280. if (0 == num_objects_inserted)
  281.   { // remove the object block hdr we just worked so hard to put in
  282.     U_INT16_T(im->imep_length) -= IMEP_OBJECT_BLOCK_SIZE;
  283.     ch->size() -= IMEP_OBJECT_BLOCK_SIZE;
  284.     return;
  285.   }
  286. im->imep_block_flags |= BLOCK_FLAG_OBJECT;
  287. ob->ob_num_objects = num_objects_inserted;
  288. assert(ob->ob_protocol_type == PROTO_TORA);
  289. // add the response list
  290. createResponseList(p);
  291. stats.num_objects_created += num_objects_inserted;
  292. stats.num_object_pkts_created++;
  293. stats.sum_response_list_sz += ob->ob_num_responses;
  294. if (verbose) 
  295.   trace("T %.9f _%d_ # obj %d seq %d #resp %d RL %s", CURRENT_TIME, ipaddr,
  296. ob->ob_num_objects, ob->ob_sequence, ob->ob_num_responses, dumpResponseList(p));
  297. if (ob->ob_num_responses > 0)
  298.   { // now make a packet to save on the rexmit queue with only the
  299.     // object block and response list in it
  300.     Packet *sp = p->copy();
  301.     struct hdr_imep *sim = HDR_IMEP(sp);
  302.     struct hdr_cmn *sch = HDR_CMN(sp);
  303.     sim->imep_block_flags &= ~(BLOCK_FLAG_ACK | BLOCK_FLAG_HELLO);
  304.     int objrep_len = U_INT16_T(im->imep_length) 
  305.       - (int) ((char*) ob - (char*) im);
  306.     bcopy(ob, (char *)(sim + 1), objrep_len);
  307.     U_INT16_T(sim->imep_length) = sizeof(struct hdr_imep) + objrep_len;
  308.     sch->size() = IP_HDR_LEN  + sizeof(struct hdr_imep) + objrep_len;
  309.     stats.num_rexmitable_pkts++;
  310.     scheduleReXmit(sp);
  311.   }
  312. }
  313. // ======================================================================
  314. // ======================================================================
  315. int 
  316. imepAgent::getResponseListSize()
  317. {
  318.   int size = 0;
  319.   for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
  320.     if (l->status() != LINK_BI) continue;
  321.     size += sizeof(struct imep_response);
  322.   }
  323.   return size;
  324. }
  325. void
  326. imepAgent::createResponseList(Packet *p)
  327. {
  328. struct hdr_cmn *ch = HDR_CMN(p);
  329. struct hdr_imep *im = HDR_IMEP(p);
  330. struct imep_object_block *ob;
  331. if((im->imep_block_flags & BLOCK_FLAG_OBJECT) == 0)
  332. return;
  333. ob = findObjectBlock(p);
  334. assert(ob);
  335. ob->ob_sequence = nextSequence();
  336. struct imep_response *r = (struct imep_response*)
  337. ((char*) im + U_INT16_T(im->imep_length));
  338. for(imepLink *l = imepLinkHead.lh_first; l; l = l->link.le_next) {
  339.         if (l->status() != LINK_BI) continue;
  340. ch->size() += sizeof(struct imep_response);
  341. U_INT16_T(im->imep_length) += sizeof(struct imep_response);
  342. ob->ob_num_responses += 1;
  343. INT32_T(r->resp_ipaddr) = l->index();
  344. r++;
  345. }
  346. }