satroute.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) 1999 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 MASH Research
  17.  *      Group at the University of California Berkeley.
  18.  * 4. Neither the name of the University nor of the Research Group may be
  19.  *    used 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.  * Contributed by Tom Henderson, UCB Daedalus Research Group, June 1999
  35.  */
  36. #ifndef lint
  37. static const char rcsid[] =
  38.     "@(#) $Header: /cvsroot/nsnam/ns-2/satellite/satroute.cc,v 1.13 2005/05/19 03:19:02 tomh Exp $";
  39. #endif
  40. #include "satroute.h"
  41. #include "sattrace.h"
  42. #include "satnode.h"
  43. #include "satlink.h"
  44. #include "route.h"
  45. #include <address.h>
  46. static class SatRouteClass:public TclClass
  47. {
  48.   public:
  49. SatRouteClass ():TclClass ("Agent/SatRoute") { }
  50. TclObject *create (int, const char *const *) {
  51.      return (new SatRouteAgent ());
  52. }
  53. } class_satroute;
  54. SatRouteAgent::SatRouteAgent (): Agent (PT_MESSAGE), maxslot_(0), nslot_(0), slot_(0)
  55. {
  56. bind ("myaddr_", &myaddr_);
  57. }
  58. SatRouteAgent::~SatRouteAgent()
  59. {
  60. if (slot_)
  61.     delete [] slot_;
  62. }
  63. void SatRouteAgent::alloc(int slot)
  64. {
  65. slot_entry *old = slot_;
  66. int n = nslot_;
  67. if (old == 0)
  68. nslot_ = 32;
  69. while (nslot_ <= slot)
  70. nslot_ <<= 1;
  71. slot_ = new slot_entry[nslot_];
  72. memset(slot_, 0, nslot_ * sizeof(slot_entry));
  73. for (int i = 0; i < n; ++i) {
  74. slot_[i].next_hop = old[i].next_hop;
  75. slot_[i].entry = old[i].entry;
  76. }
  77. delete [] old;
  78. }
  79. void SatRouteAgent::install(int slot, int nh, NsObject* p)
  80. {
  81. if (slot >= nslot_)
  82. alloc(slot);
  83. slot_[slot].next_hop = nh;
  84. slot_[slot].entry = p;
  85. if (slot >= maxslot_)
  86. maxslot_ = slot;
  87. }
  88. void SatRouteAgent::clear_slots()
  89. {
  90. if (slot_)
  91. delete [] slot_;
  92. slot_ = 0;
  93. nslot_ = 0;
  94. maxslot_ = -1;
  95. }
  96. int SatRouteAgent::command (int argc, const char *const *argv)
  97. {
  98.         Tcl& tcl = Tcl::instance();
  99.         if (argc == 2) {
  100.         }
  101.         if (argc == 3) {
  102.                if (strcmp(argv[1], "set_node") == 0) {
  103.                         node_ = (SatNode *) TclObject::lookup(argv[2]);
  104.                         if (node_ == 0) {
  105.                                 tcl.resultf("no such object %s", argv[2]);
  106.                                 return (TCL_ERROR);
  107.                         }
  108.                         return (TCL_OK);
  109. }
  110. }
  111. return (Agent::command (argc, argv));
  112. }
  113. /*
  114.  *  Find a target for the received packet
  115.  */
  116. void SatRouteAgent::forwardPacket(Packet * p)
  117. {
  118. hdr_ip *iph = hdr_ip::access(p);
  119.    hdr_cmn *hdrc = HDR_CMN (p);
  120. NsObject *link_entry_;
  121. hdrc->direction() = hdr_cmn::DOWN; // send it down the stack
  122. int dst = Address::instance().get_nodeaddr(iph->daddr());
  123. // Here we need to have an accurate encoding of the next hop routing
  124. // information
  125. if (myaddr_ == iph->daddr()) {
  126. printf("Error:  trying to forward a packet destined to self: %dn", myaddr_); 
  127. Packet::free(p);
  128. }
  129. hdrc->addr_type_ = NS_AF_INET;
  130. hdrc->last_hop_ = myaddr_; // for tracing purposes 
  131. if (SatRouteObject::instance().data_driven_computation())
  132. SatRouteObject::instance().recompute_node(myaddr_);
  133. if (SatNode::dist_routing_ == 0) {
  134. if (slot_ == 0) { // No routes to anywhere
  135. if (node_->trace())
  136. node_->trace()->traceonly(p);
  137. Packet::free(p);
  138. return;
  139. }
  140. link_entry_ = slot_[dst].entry;
  141. if (link_entry_ == 0) {
  142. if (node_->trace())
  143. node_->trace()->traceonly(p);
  144. Packet::free(p);
  145. return;
  146. }
  147. hdrc->next_hop_ = slot_[dst].next_hop;
  148. link_entry_->recv(p, (Handler *)0);
  149. return;
  150. } else {
  151. // DISTRIBUTED ROUTING LOOKUP COULD GO HERE
  152. printf("Error:  distributed routing not availablen");
  153. exit(1);
  154. }
  155. }
  156. void SatRouteAgent::recv (Packet * p, Handler *)
  157. {
  158. hdr_ip *iph = hdr_ip::access(p);
  159. hdr_cmn *cmh = hdr_cmn::access(p);
  160. if (iph->saddr() == myaddr_ && cmh->num_forwards() == 0) {
  161.   // Must be a packet I'm originating... add the IP header
  162. iph->ttl_ = IP_DEF_TTL;
  163. } else if (iph->saddr() == myaddr_) {
  164. // I received a packet that I sent.  Probably a routing loop.
  165. Packet::free(p);
  166. return;
  167. } else {
  168. // Packet I'm forwarding...
  169. // Check the TTL.  If it is zero, then discard.
  170. if(--iph->ttl_ == 0) {
  171. Packet::free(p);
  172. return;
  173. }
  174. }
  175. if ((iph->saddr() != myaddr_) && (iph->dport() == ROUTER_PORT)) {
  176. // DISTRIBUTED ROUTING PROTOCOL COULD GO HERE
  177. printf("Error:  distributed routing not availablen");
  178. exit(1);
  179. } else {
  180. forwardPacket(p);
  181. }
  182. }
  183. //###########################################################################
  184. static class SatRouteObjectClass:public TclClass
  185. {
  186.   public:
  187.         SatRouteObjectClass ():TclClass ("SatRouteObject") { }
  188.         TclObject *create (int, const char *const *) {
  189.                 return (new SatRouteObject ());
  190.         }
  191. } class_satrouteobject;
  192. SatRouteObject* SatRouteObject::instance_;
  193. SatRouteObject::SatRouteObject() : suppress_initial_computation_(0) 
  194. {
  195. bind_bool("wiredRouting_", &wiredRouting_);
  196. bind_bool("metric_delay_", &metric_delay_);
  197. bind_bool("data_driven_computation_", &data_driven_computation_);
  198. }
  199. int SatRouteObject::command (int argc, const char *const *argv)
  200. {
  201.         if (instance_ == 0)
  202.                 instance_ = this;
  203. if (argc == 2) {
  204. // While suppress_initial_computation_ may seem more 
  205. // appropriate as a bound variable, it is useful to 
  206. // implement the setting of this variable this way so that 
  207. // the ``instance_ = this'' assignment is made at the
  208. // start of simulation.
  209. if (strcmp(argv[1], "suppress_initial_computation") == 0) {
  210. suppress_initial_computation_ = 1;
  211. return (TCL_OK);
  212. }
  213. if (strcmp(argv[1], "compute_routes") == 0) {
  214. recompute();
  215. return (TCL_OK);
  216. }
  217. if (strcmp(argv[1], "dump") == 0) {
  218. printf("Dumpingn");
  219. dump();
  220. return (TCL_OK);
  221. }
  222. }
  223. return (RouteLogic::command(argc, argv));
  224. }                       
  225. // Wrapper to catch whether OTcl-based (wired-satellite) routing is enabled
  226. void SatRouteObject::insert_link(int src, int dst, double cost)
  227. {
  228. if (wiredRouting_) {
  229. Tcl::instance().evalf("[Simulator instance] sat_link_up %d %d %f", (src - 1), (dst - 1), cost);
  230. } else
  231. insert(src, dst, cost);
  232. }
  233. // Wrapper to catch whether OTcl-based (wired) routing is enabled
  234. void SatRouteObject::insert_link(int src, int dst, double cost, void* entry)
  235. {
  236. SatLinkHead* slhp = (SatLinkHead*) entry;
  237. if (wiredRouting_) {
  238. // Here we do an upcall to an instproc in ns-sat.tcl
  239. // that populates the link_(:) array
  240. Tcl::instance().evalf("[Simulator instance] sat_link_up %d %d %f %s %s", (src - 1), (dst - 1), cost, slhp->name(), slhp->queue()->name());
  241. } else
  242. insert(src, dst, cost, entry); // base class insert()
  243. }
  244. void SatRouteObject::recompute_node(int node)
  245. {
  246. compute_topology();
  247. node_compute_routes(node);
  248. populate_routing_tables(node);
  249. }
  250. void SatRouteObject::recompute()
  251. {
  252. // For very large topologies (e.g., Teledesic), we don't want to
  253. // waste a lot of time computing routes at the beginning of the
  254. // simulation.  This first if() clause suppresses route computations.
  255. if (data_driven_computation_ ||
  256.     (NOW < 0.001 && suppress_initial_computation_) ) 
  257. return;
  258. else {
  259. compute_topology();
  260. if (wiredRouting_) {
  261. Tcl::instance().evalf("[Simulator instance] compute-flat-routes");
  262. } else {
  263. compute_routes(); // base class function
  264. }
  265. populate_routing_tables();
  266. }
  267. }
  268. // Derives link adjacency information from the nodes and gives the current
  269. // topology information to the RouteLogic.
  270. void SatRouteObject::compute_topology()
  271. {
  272. Node *nodep;
  273. Phy *phytxp, *phyrxp, *phytxp2, *phyrxp2;
  274. SatLinkHead *slhp;
  275. Channel *channelp, *channelp2;
  276. int src, dst; 
  277. double delay;
  278. // wired-satellite integration
  279. if (wiredRouting_) {
  280. // There are two route objects being used
  281. // a SatRouteObject and a RouteLogic (for wired)
  282. // We need to also reset the RouteLogic one
  283. Tcl::instance().evalf("[[Simulator instance] get-routelogic] reset");
  284. }
  285. reset_all();
  286. // Compute adjacencies.  Traverse linked list of nodes 
  287.         for (nodep=Node::nodehead_.lh_first; nodep; nodep = nodep->nextnode()) {
  288.     // Cycle through the linked list of linkheads
  289.     if (!SatNode::IsASatNode(nodep->address()))
  290.         continue;
  291.     for (slhp = (SatLinkHead*) nodep->linklisthead().lh_first; slhp; 
  292.       slhp = (SatLinkHead*) slhp->nextlinkhead()) {
  293. if (slhp->type() == LINK_GSL_REPEATER)
  294.     continue;
  295. if (!slhp->linkup_)
  296.     continue;
  297. phytxp = (Phy *) slhp->phy_tx();
  298. assert(phytxp);
  299. channelp = phytxp->channel();
  300. if (!channelp) 
  301.       continue; // Not currently connected to channel
  302. // Next, look for receive interfaces on this channel
  303. phyrxp = channelp->ifhead_.lh_first;
  304. for (; phyrxp; phyrxp = phyrxp->nextchnl()) {
  305.     if (phyrxp == phytxp) {
  306. printf("Configuration error:  a transmit interface 
  307.   is a channel targetn");
  308. exit(1);
  309.     } 
  310.     if (phyrxp->head()->type() == LINK_GSL_REPEATER) {
  311. double delay_firsthop = ((SatChannel*)
  312.     channelp)->get_pdelay(phytxp->node(), 
  313.     phyrxp->node());
  314. if (!((SatLinkHead*)phyrxp->head())->linkup_)
  315.          continue;
  316. phytxp2 = ((SatLinkHead*)phyrxp->head())->phy_tx();
  317. channelp2 = phytxp2->channel();
  318. if (!channelp2) 
  319.            continue; // Not currently connected to channel
  320. phyrxp2 = channelp2->ifhead_.lh_first;
  321. for (; phyrxp2; phyrxp2 = phyrxp2->nextchnl()) {
  322.          if (phyrxp2 == phytxp2) {
  323.         printf("Config error: a transmit interface 
  324.           is a channel targetn");
  325.         exit(1);
  326.     }
  327.             // Found an adjacency relationship.
  328.             // Add this link to the RouteLogic
  329.             src = phytxp->node()->address() + 1;
  330.             dst = phyrxp2->node()->address() + 1;
  331.     if (src == dst)
  332. continue;
  333.     if (metric_delay_)
  334.                 delay = ((SatChannel*) 
  335.           channelp2)->get_pdelay(phytxp2->node(), 
  336.           phyrxp2->node());
  337.     else {
  338. delay = 1;
  339. delay_firsthop = 0;
  340.     }
  341.     insert_link(src, dst, delay+delay_firsthop, (void*)slhp);
  342. }
  343.     } else {
  344.         // Found an adjacency relationship.
  345.         // Add this link to the RouteLogic
  346.         src = phytxp->node()->address() + 1;
  347.         dst = phyrxp->node()->address() + 1;
  348. if (metric_delay_)
  349.             delay = ((SatChannel*) 
  350.               channelp)->get_pdelay(phytxp->node(), 
  351.       phyrxp->node());
  352. else
  353.     delay = 1;
  354. insert_link(src, dst, delay, (void*)slhp);
  355.     }
  356. }
  357.     }
  358. }
  359. //dump();
  360. }
  361. void SatRouteObject::populate_routing_tables(int node)
  362. {
  363. SatNode *snodep = (SatNode*) Node::nodehead_.lh_first;
  364. SatNode *snodep2;
  365. int next_hop, src, dst;
  366. NsObject *target;
  367. if (wiredRouting_) {
  368. Tcl::instance().evalf("[Simulator instance] populate-flat-classifiers [Node set nn_]");
  369. return;
  370. }
  371.         for (; snodep; snodep = (SatNode*) snodep->nextnode()) {
  372. if (!SatNode::IsASatNode(snodep->address()))
  373. continue;   
  374. // First, clear slots of the current routing table
  375. if (snodep->ragent())
  376. snodep->ragent()->clear_slots();
  377. src = snodep->address();
  378. if (node != -1 && node != src)
  379. continue;
  380. snodep2 = (SatNode*) Node::nodehead_.lh_first;
  381. for (; snodep2; snodep2 = (SatNode*) snodep2->nextnode()) {
  382.                         if (!SatNode::IsASatNode(snodep->address()))
  383.                                 continue;
  384. dst = snodep2->address();
  385. next_hop = lookup(src, dst);
  386. if (next_hop != -1 && src != dst) {
  387. // Here need to insert target into slot table
  388. target = (NsObject*) lookup_entry(src, dst);
  389. if (target == 0) {
  390. printf("Error, routelogic target ");
  391. printf("not populated %fn", NOW); 
  392. exit(1);
  393. }
  394. ((SatNode*)snodep)->ragent()->install(dst, 
  395.     next_hop, target); 
  396. }
  397. }
  398. }
  399. }
  400. int SatRouteObject::lookup(int s, int d)
  401. {                                       
  402. int src = s + 1;        
  403. int dst = d + 1;
  404. if (src >= size_ || dst >= size_) {
  405. return (-1); // Next hop = -1
  406. }
  407. return (route_[INDEX(src, dst, size_)].next_hop - 1);
  408. }
  409. void* SatRouteObject::lookup_entry(int s, int d)
  410. {                       
  411. int src = s + 1;
  412. int dst = d + 1;
  413. if (src >= size_ || dst >= size_) {
  414. return (0); // Null pointer
  415. }
  416. return (route_[INDEX(src, dst, size_)].entry);
  417. }
  418. // This method is used for debugging only
  419. void SatRouteObject::dump()
  420. {
  421. int i, src, dst;
  422. for (i = 0; i < (size_ * size_); i++) {
  423. if (adj_[i].cost != SAT_ROUTE_INFINITY) {
  424. src = i / size_ - 1;
  425. dst = i % size_ - 1;
  426. printf("Found a link from %d to %d with cost %fn", src, dst, adj_[i].cost);
  427. }
  428.         }
  429. }
  430. void SatRouteObject::node_compute_routes(int node)
  431. {
  432.         int n = size_;
  433.         int* parent = new int[n];
  434.         double* hopcnt = new double[n];
  435. #define ADJ(i, j) adj_[INDEX(i, j, size_)].cost
  436. #define ADJ_ENTRY(i, j) adj_[INDEX(i, j, size_)].entry
  437. #define ROUTE(i, j) route_[INDEX(i, j, size_)].next_hop
  438. #define ROUTE_ENTRY(i, j) route_[INDEX(i, j, size_)].entry
  439.         delete[] route_;
  440.         route_ = new route_entry[n * n];
  441.         memset((char *)route_, 0, n * n * sizeof(route_[0]));
  442.         /* compute routes only for node "node" */
  443.         int k = node + 1; // must add one to get the right offset in tables  
  444.         int v;
  445.         for (v = 0; v < n; v++) 
  446.                 parent[v] = v;
  447.         /* set the route for all neighbours first */
  448.         for (v = 1; v < n; ++v) {
  449.                 if (parent[v] != k) {
  450.                         hopcnt[v] = ADJ(k, v);
  451.                         if (hopcnt[v] != SAT_ROUTE_INFINITY) {
  452.                                 ROUTE(k, v) = v;
  453.                                 ROUTE_ENTRY(k, v) = ADJ_ENTRY(k, v);
  454.                         }
  455.                 }
  456.         }
  457.         for (v = 1; v < n; ++v) {
  458.                 /*
  459.                  * w is the node that is the nearest to the subtree
  460.                  * that has been routed
  461.                  */
  462.                 int o = 0;
  463.                 /* XXX */
  464.                 hopcnt[0] = SAT_ROUTE_INFINITY;
  465.                 int w;
  466.                 for (w = 1; w < n; w++)
  467.                         if (parent[w] != k && hopcnt[w] < hopcnt[o])
  468.                                 o = w;
  469.                 parent[o] = k;
  470.                 /*
  471.                  * update distance counts for the nodes that are
  472.                  * adjacent to o
  473.                  */
  474.                 if (o == 0)
  475.                         continue;
  476.                 for (w = 1; w < n; w++) {
  477.                         if (parent[w] != k &&
  478.                             hopcnt[o] + ADJ(o, w) < hopcnt[w]) {
  479.                                 ROUTE(k, w) = ROUTE(k, o);
  480.                                 ROUTE_ENTRY(k, w) =
  481.                                     ROUTE_ENTRY(k, o);
  482.                                 hopcnt[w] = hopcnt[o] + ADJ(o, w);
  483.                         }
  484.                 }
  485.         }
  486.         /*
  487.          * The route to yourself is yourself.
  488.          */
  489.         ROUTE(k, k) = k;
  490.         ROUTE_ENTRY(k, k) = 0; // This should not matter
  491.         delete[] hopcnt;
  492.         delete[] parent;
  493. }