path.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * path.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: path.cc,v 1.7 2005/08/25 18:58:05 johnh Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 //
00047 // Other copyrights might apply to parts of this software and are so
00048 // noted when applicable.
00049 //
00050 // Ported from CMU/Monarch's code, appropriate copyright applies.  
00051 
00052 /* path.cc
00053 
00054    handles source routes
00055 
00056 */
00057 
00058 extern "C" {
00059 #include <assert.h>
00060 #include <stdio.h>
00061 }
00062 
00063 #include <packet.h>
00064 #include <ip.h>
00065 #include "hdr_sr.h"
00066 #include "path.h"
00067 
00068 /*===========================================================================
00069   global statics
00070 ---------------------------------------------------------------------------*/
00071 
00072 ID invalid_addr(0xffffffff,::NONE);
00073 ID IP_broadcast(IP_BROADCAST,::IP);
00074 
00075 
00076 /*===========================================================================
00077   ID methods
00078 ---------------------------------------------------------------------------*/
00079 void
00080 ID::unparse(FILE *out) const
00081 {
00082   fprintf(out,"%d",(int) addr);
00083 }
00084 
00085 char *
00086 ID::dump() const
00087 {
00088   static char buf[MAX_SR_LEN+1][50];
00089   static int which = 0;
00090   char *ptr = buf[which];
00091   which = (which + 1) % (MAX_SR_LEN+1);
00092 
00093   assert(type == ::NONE || type == ::MAC || type == ::IP);
00094 
00095   if (type == ::IP)
00096     sprintf(ptr,"%d",(int) addr);
00097   else if (type == ::NONE)
00098     sprintf(ptr,"NONE");
00099   else
00100     sprintf(ptr,"0x%x",(int) addr);
00101   return ptr;
00102 }
00103 
00104 
00105 /*===========================================================================
00106   Path methods
00107 ---------------------------------------------------------------------------*/
00108 /* rep invariants:
00109    -1 <= cur_index <= len  (neither bound is really hard)
00110    0 <= len < MAX_SR_LEN
00111 */
00112 
00113 Path::Path(int route_len, const ID *route)
00114 {
00115   path = new ID[MAX_SR_LEN];
00116   assert(route_len <= MAX_SR_LEN);
00117   //  route_len = (route == NULL : 0 ? route_len); 
00118   // a more cute solution, follow the above with the then clause
00119   if (route != NULL)
00120     {
00121       for (int c = 0; c < route_len; c++)
00122         {
00123       path[c] = route[c];
00124         }
00125       len = route_len;
00126     }
00127   else
00128     {
00129       len = 0;
00130     }
00131   cur_index = 0;
00132 }
00133 
00134 Path::Path()
00135 {
00136   path = new ID[MAX_SR_LEN];
00137   len = 0;
00138   cur_index = 0;
00139 }
00140 
00141 
00142 Path::Path(const struct sr_addr *addrs, int len)
00143 { /* make a path from the bits of an NS source route header */
00144   assert(len <= MAX_SR_LEN);
00145   path = new ID[MAX_SR_LEN];
00146 
00147   for (int i = 0 ; i < len ; i++)
00148     path[i] = ID(addrs[i]);
00149 
00150   this->len = len;
00151   cur_index = 0;
00152 }
00153 
00154 Path::Path(struct hdr_sr *srh)
00155 { /* make a path from the bits of an NS source route header */
00156     path = new ID[MAX_SR_LEN];
00157 
00158     if (! srh->valid()) {
00159         len = 0;
00160         cur_index = 0;
00161         return;
00162     }
00163 
00164     len = srh->num_addrs();
00165     cur_index = srh->cur_addr();
00166 
00167     assert(len <= MAX_SR_LEN);
00168     
00169     for (int i = 0 ; i < len ; i++)
00170         path[i] = ID(srh->addrs()[i]);
00171 }
00172 
00173 void
00174 Path::fillSR(struct hdr_sr *srh)
00175 {
00176   for (int i = 0 ; i < len ; i++)
00177     {
00178       path[i].fillSRAddr(srh->addrs()[i]);
00179     }
00180   srh->num_addrs() = len;
00181   srh->cur_addr() = cur_index;
00182 }
00183 
00184 Path::Path(const Path& old)
00185 {
00186   path = new ID[MAX_SR_LEN];
00187   if (old.path != NULL)
00188     {
00189       for (int c = 0; c < old.len; c++)
00190     path[c] = old.path[c];
00191       len = old.len;
00192     }
00193   else
00194     {
00195       len = 0;
00196     }
00197   cur_index = old.cur_index;
00198   path_owner = old.path_owner;
00199 }
00200 
00201 Path::~Path()
00202 {
00203   delete[] path;
00204 }
00205 
00206 void
00207 Path::operator=(const Path &rhs)
00208      // makes the lhs a copy of the rhs: lhs may share data with
00209      // the rhs such that changes to one will be seen by the other
00210      // use the provided copy operation if you don't want this.
00211 {
00212 /* OLD  NOTE:
00213   we save copying the path by doing a delete[] path; path = rhs.path;
00214    but then the following code will be fatal (it calls delete[]
00215    twice on the same address)
00216      { Path p1();
00217        { Path p2();
00218          p2 = p1;
00219        }
00220      }
00221    you'd have to implement reference counts on the path array to
00222    save copying the path.
00223 
00224    NEW NOTE: we just copy like everything else
00225 */
00226   if (this != &rhs)
00227     {// beware of path = path (see Stroustrup p. 238)
00228       cur_index = rhs.cur_index;
00229       path_owner = rhs.path_owner;
00230       len = rhs.len;
00231       for (int c = 0 ; c < len ; c++)
00232     path[c] = rhs.path[c];
00233     }
00234   // note: i don't return *this cause I don't think assignments should
00235   // be expressions (and it has slightly incorrect semantics: (a=b) should
00236   // have the value of b, not the new value of a)
00237 }
00238 
00239 bool
00240 Path::operator==(const Path &rhs)
00241 {
00242   int c;
00243   if (len != rhs.len) return false;
00244   for (c = 0; c < len; c++)
00245     if (path[c] != rhs.path[c]) return false;
00246   return true;
00247 }
00248  
00249 void 
00250 Path::appendPath(Path& p)
00251 {
00252   int i;
00253   for (i = 0; i < p.length() ; i++)
00254     {
00255       path[len] = p[i];
00256       len++;
00257       if (len > MAX_SR_LEN)
00258     {
00259       fprintf(stderr,"DFU: overflow in appendPath len2 %d\n",
00260           p.length());
00261       len--;
00262       return;
00263     }
00264     }
00265 }
00266 
00267 void 
00268 Path::removeSection(int from, int to)
00269   // the elements at indices from -> to-1 are removed from the path
00270 {
00271   int i,j;
00272 
00273   if (to <= from) return;
00274   if (cur_index > from) cur_index = cur_index - (to - from);
00275   for (i = to, j = 0; i < len ; i++, j++)
00276     path[from + j] = path[i];
00277   len = from + j;
00278 }
00279 
00280 Path
00281 Path::copy() const
00282 {
00283   Path p(len,path);
00284   p.cur_index = cur_index;
00285   p.path_owner = path_owner;
00286   return p;
00287 }
00288 
00289 void
00290 Path::copyInto(Path& to) const
00291 {
00292   to.cur_index = cur_index;
00293   to.len = len;
00294   for (int c = 0 ; c < len ; c++)
00295     to.path[c] = path[c];  
00296   to.path_owner = path_owner;
00297 }
00298 
00299 Path
00300 Path::reverse() const
00301      // return an identical path with the index pointing to the same
00302      // host, but the path in reverse order
00303 {
00304   if (len == 0) return *this;
00305   Path p;
00306 
00307   int from, to;
00308   for (from = 0, to = (len-1) ; from < len ; from++,to--)
00309     p.path[to] = path[from];
00310   p.len = len;
00311   p.cur_index = (len - 1) - cur_index;
00312   return p;
00313 }
00314 
00315 void
00316 Path::reverseInPlace()
00317 {
00318   if (len == 0) return;
00319   int fp,bp;       // forward ptr, back ptr
00320   ID temp;
00321   for (fp = 0, bp = (len-1) ; fp < bp ; fp++, bp--)
00322     {
00323       temp = path[fp];
00324       path[fp] = path[bp];
00325       path[bp] = temp;
00326     }
00327   cur_index = (len - 1) - cur_index;
00328 }
00329 
00330 int
00331 Path::size() const
00332 {
00333   // this should be more clever and ask the id's what their sizes are.
00334   return len*4;
00335 }
00336 
00337 bool
00338 Path::member(const ID& id) const
00339 // rtn true iff id is in path
00340 {
00341   return member(id, invalid_addr);  
00342 }
00343 
00344 bool
00345 Path::member(const ID& id, const ID& MAC_id) const
00346 // rtn true iff id or MAC_id is in path
00347 {
00348   for (int c = 0; c < len ; c++)
00349     if (path[c] == id || path[c] == MAC_id)
00350       return true;
00351   return false;
00352 }
00353 
00354 void
00355 Path::unparse(FILE *out) const
00356 {
00357   // change to put ()'s around the cur_index entry?
00358   if (len==0)
00359     {
00360       fprintf(out,"<empty path>");
00361       return;
00362     }
00363   for (int c = 0 ; c < len-1 ; c ++)
00364     {
00365       if (c == cur_index) fprintf(out,"(");
00366       path[c].unparse(out);
00367       if (c == cur_index) fprintf(out,")");
00368       fprintf(out,",");
00369     }
00370   if (len-1 == cur_index) fprintf(out,"(");
00371   path[len-1].unparse(out);
00372   if (len-1 == cur_index) fprintf(out,")");
00373 }
00374 
00375 char *
00376 Path::dump() const
00377 {
00378   static int which = 0;
00379   static char buf[4][100];
00380   char *ptr = buf[which];
00381   char *rtn_buf = ptr;
00382   which = (which + 1) % 4;
00383   
00384   if (len == 0)
00385     {
00386       sprintf(rtn_buf,"[<empty path>]");
00387       return rtn_buf;
00388     }
00389   *ptr++ = '[';
00390   for (int c = 0 ; c < len ; c ++)
00391     {
00392       if (c == cur_index) *ptr++ = '(';
00393       ptr += sprintf(ptr,"%s%s ",path[c].dump(), c == cur_index ? ")" : "");
00394     }
00395   *ptr++ = ']';
00396   *ptr++ = '\0';
00397   return rtn_buf;
00398 }
00399 
00400 void
00401 compressPath(Path &path)
00402 // take a path and remove any double backs from it
00403 // eg:  A B C B D --> A B D
00404 {
00405   // idea: walk one pointer from begining
00406   //  for each elt1 start at end of path and walk a pointer backwards (elt2)
00407   //   if forward pointer = backward pointer, go on and walk foward one more
00408   //   if elt1 = elt2 then append {(elt2 + 1) to end} after forward pointer
00409   //    update length of path (we just cut out a loopback) and walk forward
00410   //  when forward walking pointer reaches end of path we're done
00411 
00412   int fp = 0, bp; // the forward walking ptr and the back walking ptr
00413   while (fp < path.len)
00414     {
00415       for (bp = path.len - 1; bp != fp; bp--)
00416     {
00417       if (path.path[fp] == path.path[bp])
00418         { int from, to;
00419           for (from = bp, to = fp;
00420            from < path.len ;
00421            from++, to++)
00422         path.path[to] = path.path[from];
00423           path.len = to;
00424           break;
00425         } // end of removing double back
00426     } // end of scaning to check for double back
00427       fp++; // advance the forward moving pointer
00428     }
00429 }
00430 
00431 void 
00432 CopyIntoPath(Path& to, const Path& from, int start, int stop)
00433 // sets to[0->(stop-start)] = from[start->stop]
00434 {
00435   assert(start >= 0 && stop < from.len);
00436   int f, t,c ;          // from and to indices
00437   for(f = start, t = 0; f <= stop; f++, t++)
00438     to.path[t] = from.path[f];
00439   if (to.len < stop - start + 1) to.len = stop - start + 1;
00440   for (c = to.len - 1; c >= 0; c--)
00441     {
00442       if (to.path[c] == to.owner()) break;
00443       if (to.path[c] == ((Path &)from).owner()) 
00444     {
00445       to.owner() = ((Path &)from).owner();
00446       break;
00447     }
00448     } 
00449 }
00450 
00451 void
00452 Path::checkpath() const
00453 {
00454   for(int c = 0; c < MAX_SR_LEN; c++)
00455     {     
00456       assert(path[c].type == NONE ||
00457              path[c].type == MAC ||
00458              path[c].type == IP);
00459     }
00460 }

Generated on Tue Mar 6 16:47:49 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6