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 #ifndef lint
00038 static const char rcsid[] =
00039 "@(#) $Header: /nfs/jade/vint/CVSROOT/ns-2/satellite/satroute.cc,v 1.12 2001/11/06 06:21:47 tomh Exp $";
00040 #endif
00041
00042 #include "satroute.h"
00043 #include "sattrace.h"
00044 #include "satnode.h"
00045 #include "satlink.h"
00046 #include "route.h"
00047 #include <address.h>
00048
00049 static class SatRouteClass:public TclClass
00050 {
00051 public:
00052 SatRouteClass ():TclClass ("Agent/SatRoute") { }
00053 TclObject *create (int, const char *const *) {
00054 return (new SatRouteAgent ());
00055 }
00056 } class_satroute;
00057
00058 SatRouteAgent::SatRouteAgent (): Agent (PT_MESSAGE), maxslot_(0), nslot_(0), slot_(0)
00059 {
00060 bind ("myaddr_", &myaddr_);
00061 }
00062
00063 SatRouteAgent::~SatRouteAgent()
00064 {
00065 if (slot_)
00066 delete [] slot_;
00067 }
00068
00069 void SatRouteAgent::alloc(int slot)
00070 {
00071 slot_entry *old = slot_;
00072 int n = nslot_;
00073 if (old == 0)
00074 nslot_ = 32;
00075 while (nslot_ <= slot)
00076 nslot_ <<= 1;
00077 slot_ = new slot_entry[nslot_];
00078 memset(slot_, 0, nslot_ * sizeof(slot_entry));
00079 for (int i = 0; i < n; ++i) {
00080 slot_[i].next_hop = old[i].next_hop;
00081 slot_[i].entry = old[i].entry;
00082 }
00083 delete [] old;
00084 }
00085
00086 void SatRouteAgent::install(int slot, int nh, NsObject* p)
00087 {
00088 if (slot >= nslot_)
00089 alloc(slot);
00090 slot_[slot].next_hop = nh;
00091 slot_[slot].entry = p;
00092 if (slot >= maxslot_)
00093 maxslot_ = slot;
00094 }
00095
00096 void SatRouteAgent::clear_slots()
00097 {
00098 if (slot_)
00099 delete [] slot_;
00100 slot_ = 0;
00101 nslot_ = 0;
00102 maxslot_ = -1;
00103 }
00104
00105 int SatRouteAgent::command (int argc, const char *const *argv)
00106 {
00107 Tcl& tcl = Tcl::instance();
00108 if (argc == 2) {
00109 }
00110 if (argc == 3) {
00111 if (strcmp(argv[1], "set_node") == 0) {
00112 node_ = (SatNode *) TclObject::lookup(argv[2]);
00113 if (node_ == 0) {
00114 tcl.resultf("no such object %s", argv[2]);
00115 return (TCL_ERROR);
00116 }
00117 return (TCL_OK);
00118 }
00119 }
00120 return (Agent::command (argc, argv));
00121 }
00122
00123
00124
00125
00126 void SatRouteAgent::forwardPacket(Packet * p)
00127 {
00128 hdr_ip *iph = hdr_ip::access(p);
00129 hdr_cmn *hdrc = HDR_CMN (p);
00130 NsObject *link_entry_;
00131
00132 hdrc->direction() = hdr_cmn::DOWN;
00133 int dst = Address::instance().get_nodeaddr(iph->daddr());
00134
00135
00136 if (myaddr_ == iph->daddr()) {
00137 printf("Error: trying to forward a packet destined to self: %d\n", myaddr_);
00138 Packet::free(p);
00139 }
00140 hdrc->addr_type_ = NS_AF_INET;
00141 hdrc->last_hop_ = myaddr_;
00142 if (SatRouteObject::instance().data_driven_computation())
00143 SatRouteObject::instance().recompute_node(myaddr_);
00144 if (SatNode::dist_routing_ == 0) {
00145 if (slot_ == 0) {
00146 if (node_->trace())
00147 node_->trace()->traceonly(p);
00148 Packet::free(p);
00149 return;
00150 }
00151 link_entry_ = slot_[dst].entry;
00152 if (link_entry_ == 0) {
00153 if (node_->trace())
00154 node_->trace()->traceonly(p);
00155 Packet::free(p);
00156 return;
00157 }
00158 hdrc->next_hop_ = slot_[dst].next_hop;
00159 link_entry_->recv(p, (Handler *)0);
00160 return;
00161 } else {
00162
00163 printf("Error: distributed routing not available\n");
00164 exit(1);
00165 }
00166 }
00167
00168 void SatRouteAgent::recv (Packet * p, Handler *)
00169 {
00170 hdr_ip *iph = hdr_ip::access(p);
00171 hdr_cmn *cmh = hdr_cmn::access(p);
00172
00173 if (iph->saddr() == myaddr_ && cmh->num_forwards() == 0) {
00174
00175 iph->ttl_ = IP_DEF_TTL;
00176 } else if (iph->saddr() == myaddr_) {
00177
00178 Packet::free(p);
00179 return;
00180 } else {
00181
00182
00183 if(--iph->ttl_ == 0) {
00184 Packet::free(p);
00185 return;
00186 }
00187 }
00188 if ((iph->saddr() != myaddr_) && (iph->dport() == ROUTER_PORT)) {
00189
00190 printf("Error: distributed routing not available\n");
00191 exit(1);
00192 } else {
00193 forwardPacket(p);
00194 }
00195 }
00196
00197
00198
00199 static class SatRouteObjectClass:public TclClass
00200 {
00201 public:
00202 SatRouteObjectClass ():TclClass ("SatRouteObject") { }
00203 TclObject *create (int, const char *const *) {
00204 return (new SatRouteObject ());
00205 }
00206 } class_satrouteobject;
00207
00208 SatRouteObject* SatRouteObject::instance_;
00209
00210 SatRouteObject::SatRouteObject() : suppress_initial_computation_(0)
00211 {
00212 bind_bool("wiredRouting_", &wiredRouting_);
00213 bind_bool("metric_delay_", &metric_delay_);
00214 bind_bool("data_driven_computation_", &data_driven_computation_);
00215 }
00216
00217 int SatRouteObject::command (int argc, const char *const *argv)
00218 {
00219 if (instance_ == 0)
00220 instance_ = this;
00221 if (argc == 2) {
00222
00223
00224
00225
00226
00227 if (strcmp(argv[1], "suppress_initial_computation") == 0) {
00228 suppress_initial_computation_ = 1;
00229 return (TCL_OK);
00230 }
00231 if (strcmp(argv[1], "compute_routes") == 0) {
00232 recompute();
00233 return (TCL_OK);
00234 }
00235 if (strcmp(argv[1], "dump") == 0) {
00236 printf("Dumping\n");
00237 dump();
00238 return (TCL_OK);
00239 }
00240 }
00241 return (RouteLogic::command(argc, argv));
00242 }
00243
00244
00245 void SatRouteObject::insert_link(int src, int dst, double cost)
00246 {
00247 if (wiredRouting_) {
00248 Tcl::instance().evalf("[Simulator instance] sat_link_up %d %d %f", (src - 1), (dst - 1), cost);
00249 } else
00250 insert(src, dst, cost);
00251 }
00252
00253
00254 void SatRouteObject::insert_link(int src, int dst, double cost, void* entry)
00255 {
00256 SatLinkHead* slhp = (SatLinkHead*) entry;
00257 if (wiredRouting_) {
00258
00259
00260 Tcl::instance().evalf("[Simulator instance] sat_link_up %d %d %f %s %s", (src - 1), (dst - 1), cost, slhp->name(), slhp->queue()->name());
00261 } else
00262 insert(src, dst, cost, entry);
00263 }
00264
00265 void SatRouteObject::recompute_node(int node)
00266 {
00267 compute_topology();
00268 node_compute_routes(node);
00269 populate_routing_tables(node);
00270 }
00271 void SatRouteObject::recompute()
00272 {
00273
00274
00275
00276 if (data_driven_computation_ ||
00277 (NOW < 0.001 && suppress_initial_computation_) )
00278 return;
00279 else {
00280 compute_topology();
00281 if (wiredRouting_) {
00282 Tcl::instance().evalf("[Simulator instance] compute-flat-routes");
00283 } else {
00284 compute_routes();
00285 }
00286 populate_routing_tables();
00287 }
00288 }
00289
00290
00291
00292 void SatRouteObject::compute_topology()
00293 {
00294 Node *nodep;
00295 Phy *phytxp, *phyrxp, *phytxp2, *phyrxp2;
00296 SatLinkHead *slhp;
00297 Channel *channelp, *channelp2;
00298 int src, dst;
00299 double delay;
00300
00301
00302 if (wiredRouting_) {
00303
00304
00305
00306 Tcl::instance().evalf("[[Simulator instance] get-routelogic] reset");
00307 }
00308 reset_all();
00309
00310 for (nodep=Node::nodehead_.lh_first; nodep; nodep = nodep->nextnode()) {
00311
00312 if (!SatNode::IsASatNode(nodep->address()))
00313 continue;
00314 for (slhp = (SatLinkHead*) nodep->linklisthead().lh_first; slhp;
00315 slhp = (SatLinkHead*) slhp->nextlinkhead()) {
00316 if (slhp->type() == LINK_GSL_REPEATER)
00317 continue;
00318 if (!slhp->linkup_)
00319 continue;
00320 phytxp = (Phy *) slhp->phy_tx();
00321 assert(phytxp);
00322 channelp = phytxp->channel();
00323 if (!channelp)
00324 continue;
00325
00326 phyrxp = channelp->ifhead_.lh_first;
00327 for (; phyrxp; phyrxp = phyrxp->nextchnl()) {
00328 if (phyrxp == phytxp) {
00329 printf("Configuration error: a transmit interface \
00330 is a channel target\n");
00331 exit(1);
00332 }
00333 if (phyrxp->head()->type() == LINK_GSL_REPEATER) {
00334 double delay_firsthop = ((SatChannel*)
00335 channelp)->get_pdelay(phytxp->node(),
00336 phyrxp->node());
00337 if (!((SatLinkHead*)phyrxp->head())->linkup_)
00338 continue;
00339 phytxp2 = ((SatLinkHead*)phyrxp->head())->phy_tx();
00340 channelp2 = phytxp2->channel();
00341 if (!channelp2)
00342 continue;
00343 phyrxp2 = channelp2->ifhead_.lh_first;
00344 for (; phyrxp2; phyrxp2 = phyrxp2->nextchnl()) {
00345 if (phyrxp2 == phytxp2) {
00346 printf("Config error: a transmit interface \
00347 is a channel target\n");
00348 exit(1);
00349 }
00350
00351
00352 src = phytxp->node()->address() + 1;
00353 dst = phyrxp2->node()->address() + 1;
00354 if (src == dst)
00355 continue;
00356 if (metric_delay_)
00357 delay = ((SatChannel*)
00358 channelp2)->get_pdelay(phytxp2->node(),
00359 phyrxp2->node());
00360 else {
00361 delay = 1;
00362 delay_firsthop = 0;
00363 }
00364 insert_link(src, dst, delay+delay_firsthop, (void*)slhp);
00365 }
00366 } else {
00367
00368
00369 src = phytxp->node()->address() + 1;
00370 dst = phyrxp->node()->address() + 1;
00371 if (metric_delay_)
00372 delay = ((SatChannel*)
00373 channelp)->get_pdelay(phytxp->node(),
00374 phyrxp->node());
00375 else
00376 delay = 1;
00377 insert_link(src, dst, delay, (void*)slhp);
00378 }
00379 }
00380 }
00381 }
00382
00383 }
00384
00385 void SatRouteObject::populate_routing_tables(int node)
00386 {
00387 SatNode *snodep = (SatNode*) Node::nodehead_.lh_first;
00388 SatNode *snodep2;
00389 int next_hop, src, dst;
00390 NsObject *target;
00391
00392 if (wiredRouting_) {
00393 Tcl::instance().evalf("[Simulator instance] populate-flat-classifiers [Node set nn_]");
00394 return;
00395 }
00396 for (; snodep; snodep = (SatNode*) snodep->nextnode()) {
00397 if (!SatNode::IsASatNode(snodep->address()))
00398 continue;
00399
00400 if (snodep->ragent())
00401 snodep->ragent()->clear_slots();
00402 src = snodep->address();
00403 if (node != -1 && node != src)
00404 continue;
00405 snodep2 = (SatNode*) Node::nodehead_.lh_first;
00406 for (; snodep2; snodep2 = (SatNode*) snodep2->nextnode()) {
00407 if (!SatNode::IsASatNode(snodep->address()))
00408 continue;
00409 dst = snodep2->address();
00410 next_hop = lookup(src, dst);
00411 if (next_hop != -1 && src != dst) {
00412
00413 target = (NsObject*) lookup_entry(src, dst);
00414 if (target == 0) {
00415 printf("Error, routelogic target ");
00416 printf("not populated %f\n", NOW);
00417 exit(1);
00418 }
00419 ((SatNode*)snodep)->ragent()->install(dst,
00420 next_hop, target);
00421 }
00422 }
00423 }
00424
00425 }
00426
00427 int SatRouteObject::lookup(int s, int d)
00428 {
00429 int src = s + 1;
00430 int dst = d + 1;
00431 if (src >= size_ || dst >= size_) {
00432 return (-1);
00433 }
00434 return (route_[INDEX(src, dst, size_)].next_hop - 1);
00435 }
00436
00437 void* SatRouteObject::lookup_entry(int s, int d)
00438 {
00439 int src = s + 1;
00440 int dst = d + 1;
00441 if (src >= size_ || dst >= size_) {
00442 return (0);
00443 }
00444 return (route_[INDEX(src, dst, size_)].entry);
00445 }
00446
00447
00448 void SatRouteObject::dump()
00449 {
00450 int i, src, dst;
00451 for (i = 0; i < (size_ * size_); i++) {
00452 if (adj_[i].cost != INFINITY) {
00453 src = i / size_ - 1;
00454 dst = i % size_ - 1;
00455 printf("Found a link from %d to %d with cost %f\n", src, dst, adj_[i].cost);
00456 }
00457 }
00458 }
00459
00460 void SatRouteObject::node_compute_routes(int node)
00461 {
00462 int n = size_;
00463 int* parent = new int[n];
00464 double* hopcnt = new double[n];
00465 #define ADJ(i, j) adj_[INDEX(i, j, size_)].cost
00466 #define ADJ_ENTRY(i, j) adj_[INDEX(i, j, size_)].entry
00467 #define ROUTE(i, j) route_[INDEX(i, j, size_)].next_hop
00468 #define ROUTE_ENTRY(i, j) route_[INDEX(i, j, size_)].entry
00469 delete[] route_;
00470 route_ = new route_entry[n * n];
00471 memset((char *)route_, 0, n * n * sizeof(route_[0]));
00472
00473 int k = node + 1;
00474 int v;
00475 for (v = 0; v < n; v++)
00476 parent[v] = v;
00477
00478
00479 for (v = 1; v < n; ++v) {
00480 if (parent[v] != k) {
00481 hopcnt[v] = ADJ(k, v);
00482 if (hopcnt[v] != INFINITY) {
00483 ROUTE(k, v) = v;
00484 ROUTE_ENTRY(k, v) = ADJ_ENTRY(k, v);
00485 }
00486 }
00487 }
00488 for (v = 1; v < n; ++v) {
00489
00490
00491
00492
00493 int o = 0;
00494
00495 hopcnt[0] = INFINITY;
00496 int w;
00497 for (w = 1; w < n; w++)
00498 if (parent[w] != k && hopcnt[w] < hopcnt[o])
00499 o = w;
00500 parent[o] = k;
00501
00502
00503
00504
00505 if (o == 0)
00506 continue;
00507 for (w = 1; w < n; w++) {
00508 if (parent[w] != k &&
00509 hopcnt[o] + ADJ(o, w) < hopcnt[w]) {
00510 ROUTE(k, w) = ROUTE(k, o);
00511 ROUTE_ENTRY(k, w) =
00512 ROUTE_ENTRY(k, o);
00513 hopcnt[w] = hopcnt[o] + ADJ(o, w);
00514 }
00515 }
00516 }
00517
00518
00519
00520 ROUTE(k, k) = k;
00521 ROUTE_ENTRY(k, k) = 0;
00522
00523 delete[] hopcnt;
00524 delete[] parent;
00525 }