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

通讯编程

开发平台:

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.  * $Header: /cvsroot/nsnam/ns-2/tora/tora.cc,v 1.18 2005/08/28 23:23:03 tomh Exp $
  37.  */
  38. #include <agent.h>
  39. #include <random.h>
  40. #include <trace.h>
  41. #include <ll.h>
  42. #include <priqueue.h>
  43. #include <tora/tora_packet.h>
  44. #include <tora/tora.h>
  45. #define LOG(s)
  46. fprintf(stdout, "%s --- %s (index: %d, time: %f)n",
  47. __PRETTY_FUNCTION__, (s), index, Scheduler::instance().clock())
  48. // #define DEBUG
  49. #define CURRENT_TIME Scheduler::instance().clock()
  50. /* sec of spacing inserted between pkts when a bunch of packets are
  51.    dumped into the link layer all at once.  Allows arp time to resolve
  52.    dst, preventing the dumping of all but the last pkt on the floor */
  53. #define ARP_SEPARATION_DELAY 0.030
  54.   
  55. /* ======================================================================
  56.    TCL Hooks
  57.    ====================================================================== */
  58. int hdr_tora::offset_;
  59. static class TORAHeaderClass : public PacketHeaderClass {
  60. public:
  61.         TORAHeaderClass() : PacketHeaderClass("PacketHeader/TORA",
  62.       TORA_HDR_LEN) { 
  63. bind_offset(&hdr_tora::offset_);
  64. } class_toraAgent_hdr;
  65. static class toraAgentclass : public TclClass {
  66. public:
  67. toraAgentclass() : TclClass("Agent/TORA") {}
  68. TclObject* create(int argc, const char*const* argv) {
  69. assert(argc == 5);
  70. return (new toraAgent((nsaddr_t) atoi(argv[4])));
  71. }
  72. } class_toraAgent;
  73. /* ======================================================================
  74.    toraAgent Class Functions
  75.    ====================================================================== */
  76. toraAgent::toraAgent(nsaddr_t id) :
  77. rtAgent(id, PT_TORA),
  78. rqueue()
  79. {
  80. LIST_INIT(&dstlist);
  81. imepagent = 0;
  82. logtarget = 0;
  83. ifqueue = 0;
  84. }
  85. void
  86. toraAgent::reset()
  87. {
  88. Packet *p;
  89. while((p = rqueue.deque())) {
  90. drop(p,DROP_END_OF_SIMULATION);
  91. }
  92. }
  93. int
  94. toraAgent::command(int argc, const char*const* argv)
  95. {
  96. if(argc == 2) {
  97. Tcl& tcl = Tcl::instance();
  98. if(strncasecmp(argv[1], "id", 2) == 0) {
  99. tcl.resultf("%d", index);
  100. return TCL_OK;
  101. }
  102. }
  103. else if(argc == 3) {
  104. if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0 ) {
  105. logtarget = (Trace*) TclObject::lookup(argv[2]);
  106. if(logtarget == 0)
  107. return TCL_ERROR;
  108. return TCL_OK;
  109. }
  110. else if(strcmp(argv[1], "drop-target") == 0) {
  111.         int stat = rqueue.command(argc,argv);
  112. if (stat != TCL_OK) return stat;
  113.                  return Agent::command(argc, argv);
  114. }
  115. else if(strcmp(argv[1], "if-queue") == 0) {
  116. ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
  117. if(ifqueue == 0)
  118. return TCL_ERROR;
  119. return TCL_OK;
  120. }
  121. else if(strcmp(argv[1], "imep-agent") == 0) {
  122. imepagent = (imepAgent*) TclObject::lookup(argv[2]);
  123. if(imepagent == 0)
  124. return TCL_ERROR;
  125. imepagent->imepRegister((rtAgent*) this);
  126. return TCL_OK;
  127. }
  128. }
  129. return Agent::command(argc, argv);
  130. }
  131. /* ======================================================================
  132.    Destination Management Functions
  133.    ====================================================================== */
  134. TORADest*
  135. toraAgent::dst_find(nsaddr_t id)
  136. {
  137. TORADest* td = dstlist.lh_first;
  138. for( ; td; td = td->link.le_next) {
  139. if(td->index == id)
  140. return td;
  141. }
  142. return 0;
  143. }
  144. TORADest*
  145. toraAgent::dst_add(nsaddr_t id)
  146. {
  147. TORADest *td = new TORADest(id, this);
  148. assert(td);
  149. LIST_INSERT_HEAD(&dstlist, td, link);
  150. int *nblist = 0, nbcnt = 0;
  151. imepagent->imepGetBiLinks(nblist, nbcnt);
  152. for(int i = 0; i < nbcnt; i++)
  153. (void) td->nb_add(nblist[i]);
  154. if(nblist) delete[] nblist;
  155. return td;
  156. }
  157. void
  158. toraAgent::dst_dump()
  159. {
  160. TORADest *td = dstlist.lh_first;
  161. for( ; td; td = td->link.le_next)
  162. td->dump();
  163. }
  164. /* ======================================================================
  165.    Route Resolution
  166.    ====================================================================== */
  167. void
  168. toraAgent::forward(Packet *p, nsaddr_t nexthop, Time delay)
  169. {
  170.         struct hdr_cmn *ch = HDR_CMN(p);
  171. #ifdef TORA_DISALLOW_ROUTE_LOOP
  172.         if(nexthop == ch->prev_hop_) {
  173. log_route_loop(ch->prev_hop_, nexthop);
  174.                 drop(p, DROP_RTR_ROUTE_LOOP);
  175.                 return;
  176.         }
  177. #endif
  178.         ch->next_hop() = nexthop;
  179.         ch->prev_hop_ = ipaddr();
  180.         ch->addr_type() = NS_AF_INET;
  181. // change the packet direction to DOWN
  182. ch->direction() = hdr_cmn::DOWN;
  183. if (0.0 == delay) {
  184.   tora_output(p);
  185. } else {
  186.   Scheduler::instance().schedule(target_, p, delay);
  187. }
  188. }
  189. void
  190. toraAgent::rt_resolve(Packet *p)
  191. {
  192. struct hdr_ip *ih = HDR_IP(p);
  193. TORADest *td;
  194. TORANeighbor *tn;
  195. td = dst_find(ih->daddr());
  196. if(td == 0) {
  197. td = dst_add(ih->daddr());
  198. }
  199. tn = td->nb_find_next_hop();
  200. if(tn == 0) {
  201. rqueue.enque(p);
  202. trace("T %.9f _%d_ tora enq %d->%d",
  203.       Scheduler::instance().clock(), ipaddr(), 
  204.       ih->saddr(), ih->daddr());
  205. if(!td->rt_req)
  206.   { // if no QRY pending, then send one
  207.     sendQRY(ih->daddr());
  208.     td->time_tx_qry = CURRENT_TIME;
  209.     td->rt_req = 1;
  210.   }
  211. }
  212. else {
  213.                 forward(p, tn->index);
  214. }
  215. }
  216. /* ======================================================================
  217.    Incoming Packets
  218.    ====================================================================== */
  219. void
  220. toraAgent::recv(Packet *p, Handler *)
  221. {
  222. struct hdr_cmn *ch = HDR_CMN(p);
  223. struct hdr_ip *ih = HDR_IP(p);
  224. assert(initialized());
  225. if(ch->ptype() == PT_TORA) {
  226. recvTORA(p);
  227. return;
  228. }
  229.         /*
  230.          *  Must be a packet I'm originating...
  231.          */
  232. if(ih->saddr() == ipaddr() && ch->num_forwards() == 0) {
  233.                 /*
  234.                  *  Add the IP Header.
  235.                  */
  236.                 ch->size() += IP_HDR_LEN;
  237.                 
  238.                 ih->ttl_ = IP_DEF_TTL;
  239. }
  240. #ifdef TORA_DISALLOW_ROUTE_LOOP
  241.         /*
  242.          *  I received a packet that I sent.  Probably
  243.          *  a routing loop.
  244.          */
  245.         else if(ih->saddr() == ipaddr()) {
  246.                 drop(p, DROP_RTR_ROUTE_LOOP);
  247.                 return;
  248.         }
  249. #endif
  250. /*
  251.  *  Packet I'm forwarding...
  252.  */
  253. else {
  254. /*
  255.  *  Check the TTL.  If it is zero, then discard.
  256.  */
  257. if(--ih->ttl_ == 0) {
  258. drop(p, DROP_RTR_TTL);
  259. return;
  260. }
  261. }
  262. rt_resolve(p);
  263. }
  264. void
  265. toraAgent::recvTORA(Packet *p)
  266. {
  267. struct hdr_tora *th = HDR_TORA(p);
  268. TORADest *td;
  269. TORANeighbor *tn;
  270. /*
  271.  * Fix the source IP address.
  272.  */
  273. assert(HDR_IP (p)->sport() == RT_PORT);
  274. assert(HDR_IP (p)->dport() == RT_PORT);
  275. /*
  276.  * Incoming Packets.
  277.  */
  278. switch(th->th_type) {
  279. case TORATYPE_QRY:
  280. recvQRY(p);
  281. Packet::free(p);
  282. return; // don't add/change routing state
  283. case TORATYPE_UPD:
  284. log_recv_upd(p);
  285. recvUPD(p);
  286. break;
  287. case TORATYPE_CLR:
  288. log_recv_clr(p);
  289. recvCLR(p);
  290. break;
  291. default:
  292. fprintf(stderr,
  293. "%s: Invalid TORA type (%x)n",
  294. __PRETTY_FUNCTION__, th->th_type);
  295. exit(1);
  296. }
  297. if((td = dst_find(th->th_dst)) == 0) {
  298. Packet::free(p);
  299. return;
  300. }
  301. logNextHopChange(td);
  302. if((tn = td->nb_find_next_hop())) {
  303. Packet *p0;
  304. Time delay = 0.0;
  305. while((p0 = rqueue.deque(td->index))) {
  306.                         forward(p0, tn->index, delay);
  307. delay += ARP_SEPARATION_DELAY;
  308. }
  309. }
  310. Packet::free(p);
  311. }
  312. /*
  313.  *  IETF Draft - TORA Specification, section 3.7.6
  314.  */
  315. void
  316. toraAgent::recvQRY(Packet *p)
  317. {
  318. struct hdr_ip *ih = HDR_IP(p);
  319. struct hdr_tora_qry *qh = HDR_TORA_QRY(p);
  320. TORADest *td;
  321. TORANeighbor *tn;
  322. if(qh->tq_dst == ipaddr()) {
  323. #ifdef DEBUG
  324. fprintf(stderr, "node %d received `QRY` for itself.n", index);
  325. #endif
  326. return;
  327. }
  328. td = dst_find(qh->tq_dst);
  329. if(td == 0)
  330. td = dst_add(qh->tq_dst);
  331. if(td->rt_req) {
  332. return;
  333. }
  334. if(td->height.r == 0) { // II, A
  335. tn = td->nb_find(ih->saddr());
  336. if(tn && tn->time_act > td->time_upd) { // II, A, 1
  337. td->time_upd = Scheduler::instance().clock();
  338. sendUPD(td->index);
  339. }
  340. else { // II, A, 2
  341. }
  342. }
  343. else {
  344. tn = td->nb_find_min_height(0);
  345. if(tn) { // II, B, 1
  346. td->update_height(tn->height.tau,
  347.   tn->height.oid,
  348.   tn->height.r,
  349.   tn->height.delta + 1,
  350.   ipaddr());
  351. td->time_upd = Scheduler::instance().clock();
  352. sendUPD(td->index);
  353. }
  354. else {
  355. td->rt_req = 1;
  356. td->time_rt_req = CURRENT_TIME;
  357. if(td->num_active > 1) { // II, B, 1, a
  358. sendQRY(td->index);
  359. }
  360. else { // II, B, 1, b
  361. }
  362. }
  363. }
  364. }
  365. /*
  366.  *  IETF Draft - TORA Specification, section 3.7.7
  367.  */
  368. void
  369. toraAgent::recvUPD(Packet *p)
  370. {
  371. struct hdr_ip *ih = HDR_IP(p);
  372. struct hdr_tora_upd *uh = HDR_TORA_UPD(p);
  373. TORADest *td;
  374. TORANeighbor *tn;
  375. if(uh->tu_dst == ipaddr()) {
  376. return;
  377. }
  378. td = dst_find(uh->tu_dst);
  379. if(td == 0)
  380. td = dst_add(uh->tu_dst);
  381. tn = td->nb_find(ih->saddr());
  382. if(tn == 0) {
  383. /*
  384.  * update link status? -josh
  385.  */
  386.          // No, don't update linkstatus: it may be an update
  387.          // that was delayed in the IMEP layer for sequencing -dam
  388.          // no way at the TORA level to tell if we're connected...
  389.          trace("T %.9f _%d_ received `UPD` from non-neighbor %d",
  390.        CURRENT_TIME, ipaddr(), ih->saddr());  
  391. #ifdef DEBUG
  392. fprintf(stderr,
  393.                         "node %d received `UPD` from non-neighbor %dn",
  394. index, ih->src_);
  395. #endif
  396. return;
  397. }
  398. /*
  399.  *  Update height and link status for neighbor [j][k].
  400.  */
  401. td->update_height_nb(tn, uh);
  402. if(td->rt_req && tn->height.r == 0) { // I
  403. td->update_height(tn->height.tau,
  404.   tn->height.oid,
  405.   tn->height.r,
  406.   tn->height.delta + 1,
  407.   ipaddr());
  408. td->rt_req = 0;
  409. td->time_upd = Scheduler::instance().clock();
  410. sendUPD(td->index);
  411. }
  412. else if(td->num_down == 0) { // II
  413. if(td->num_up == 0) { // II, A
  414. if(td->height.isNull()) // II, A, 1
  415. return; // II, A, 1, a
  416. else {
  417. td->height.Null(); // II, A, 1, b 
  418. td->time_upd = Scheduler::instance().clock();
  419. sendUPD(td->index);
  420. }
  421. }
  422. else {
  423. if(td->nb_check_same_ref()) { // II, A, 2
  424. TORANeighbor *tn;
  425. if( (tn = td->nb_find_min_height(0)) ) { // II, A, 2, a
  426. td->update_height(tn->height.tau, // II, A, 2, a, i 
  427.   tn->height.oid,
  428.   1,
  429.   0,
  430.   ipaddr());
  431. td->time_upd = Scheduler::instance().clock();
  432. sendUPD(td->index);
  433. }
  434. else {
  435. if(td->height.oid == ipaddr()) { // II, A, 2, a, ii
  436. double temp_tau = td->height.tau; // II, A, 2, a, ii, x 
  437. nsaddr_t temp_oid = td->height.oid;
  438. td->height.Null();
  439. td->num_down = 0;
  440. td->num_up = 0;
  441. /*
  442.  *  For every active link n, if the neighbor connected
  443.  *  via link n is the destination j, set HT_NEIGH[j][n]=ZERO
  444.  *  and LNK_STAT[j][n] = DN.
  445.  *  Otherwise, set HT_NEIGH[j][n] = NULL and LNK_STAT[j][n] = UN.
  446.  */
  447. for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
  448. if(tn->index == td->index) {
  449. tn->height.Zero();
  450. tn->lnk_stat = LINK_DN;
  451. }
  452. else {
  453. tn->height.Null();
  454. tn->lnk_stat = LINK_UN;
  455. }
  456. }
  457. sendCLR(td->index, temp_tau, temp_oid);
  458. }
  459. else {
  460. td->update_height(Scheduler::instance().clock(), // II, A, 2, a, ii, y
  461.   ipaddr(),
  462.   0,
  463.   0,
  464.   ipaddr());
  465. td->rt_req = 0;
  466. td->time_upd = Scheduler::instance().clock();
  467. #ifdef DEBUG
  468. // under what circumstances does this rule fire?
  469. // seems like it will prevent the detection of 
  470. // partitions...??? -dam 8/24/98
  471. if (logtarget) 
  472.   {
  473.     sprintf(logtarget->pt_->buffer(), "T %.9f _%d_ rule IIA2a(ii)x fires %d",
  474.     Scheduler::instance().clock(), ipaddr(), td->index);
  475.     logtarget->pt_->dump();
  476.   }
  477. #endif
  478. sendUPD(td->index);
  479. }
  480. }
  481. }
  482. else {
  483. TORANeighbor *n = td->nb_find_max_height(); // II, A, 2, b
  484. assert(n);
  485. TORANeighbor *m = td->nb_find_min_nonnull_height(&n->height);
  486. assert(m);
  487. td->update_height(m->height.tau,
  488.   m->height.oid,
  489.   m->height.r,
  490.   m->height.delta - 1,
  491.   ipaddr());
  492. td->time_upd = Scheduler::instance().clock();
  493. sendUPD(td->index);
  494. }
  495. }
  496. }
  497. else { // II, B
  498. }
  499. }
  500. /*
  501.  *  IETF Draft - TORA Specification, section 3.7.8
  502.  */
  503. void
  504. toraAgent::recvCLR(Packet *p)
  505. {
  506. struct hdr_ip *ih = HDR_IP(p);
  507. struct hdr_tora_clr *th = HDR_TORA_CLR(p);
  508. TORADest *td;
  509. TORANeighbor *tn;
  510. if(th->tc_dst == ipaddr()) {
  511. return;
  512. }
  513. td = dst_find(th->tc_dst);
  514. if(td == 0)
  515. td = dst_add(th->tc_dst);
  516. assert(td);
  517. if(td->height.tau == th->tc_tau &&
  518.    td->height.oid == th->tc_oid &&
  519.    td->height.r == 1) { // I
  520. double temp_tau = td->height.tau;
  521. nsaddr_t temp_oid = td->height.oid;
  522. td->height.Null();
  523. td->num_up = 0;
  524. td->num_down = 0;
  525. for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
  526. if(tn->index == td->index) {
  527. tn->height.Zero();
  528. tn->lnk_stat = LINK_DN;
  529. }
  530. else {
  531. tn->height.Null();
  532. tn->lnk_stat = LINK_UN;
  533. }
  534. }
  535. if(td->num_active > 1) { // I, A
  536. sendCLR(td->index, temp_tau, temp_oid);
  537. }
  538. else { // I, B
  539. }
  540. }
  541. else {
  542. tn = td->nb_find(ih->saddr()); // II
  543. if(tn == 0) {
  544. /*
  545.  *  XXX - update link status?
  546.  */
  547.         trace("T %.9f _%d_ received `CLR` from non-neighbor %d",
  548.                CURRENT_TIME, index, ih->saddr());
  549. #ifdef DEBUG
  550. fprintf(stderr,
  551. "node %d received `CLR` from non-neighbor %dn",
  552. index, ih->src_);
  553. #endif
  554. return;
  555. }
  556. tn->height.Null();
  557. tn->lnk_stat = LINK_UN;
  558. for(tn = td->nblist.lh_first; tn; tn = tn->link.le_next) {
  559. if(tn->height.tau == th->tc_tau &&
  560.    tn->height.oid == th->tc_oid &&
  561.    tn->height.r == 1) {
  562. tn->height.Null();
  563. tn->lnk_stat = LINK_UN;
  564.                         }
  565. }
  566. if(td->num_down == 0) { // II, A
  567. if(td->num_up == 0) { // II, A, 1
  568. if(td->height.isNull()) { // II, A, 1, a
  569. }
  570. else {
  571. td->height.Null();
  572. td->time_upd = Scheduler::instance().clock();
  573. sendUPD(td->index);
  574. }
  575. }
  576. else {
  577. td->update_height(Scheduler::instance().clock(),
  578.   ipaddr(),
  579.   0,
  580.   0,
  581.   ipaddr());
  582. td->rt_req = 0;
  583. td->time_upd = Scheduler::instance().clock();
  584. sendUPD(td->index);
  585. }
  586. }
  587. else {
  588. // II, B
  589. }
  590. }
  591. }
  592. void
  593. toraAgent::trace(char* fmt, ...)
  594. {
  595.   va_list ap;
  596.   
  597.   if (!logtarget) return;
  598.   va_start(ap, fmt);
  599.   vsprintf(logtarget->pt_->buffer(), fmt, ap);
  600.   logtarget->pt_->dump();
  601.   va_end(ap);
  602. }