flowstruct.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * flowstruct.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: flowstruct.cc,v 1.4 2005/08/25 18:58:04 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 
00053 #include "flowstruct.h"
00054 
00055 FlowTable::FlowTable(int size_) : DRTab(size_) {
00056     assert (size_ > 0);
00057     size = 0;
00058     maxSize = size_;
00059     table = new TableEntry[size_];
00060     counter = 0;
00061 }
00062 
00063 FlowTable::~FlowTable() {
00064     delete table;
00065 }
00066 
00067 TableEntry &FlowTable::operator[](int index) {
00068     assert(index >= 0 && index < size);
00069     return table[index];
00070 }
00071 
00072 int FlowTable::find(nsaddr_t source, nsaddr_t destination, u_int16_t flow) {
00073     register int i;
00074     for (i=size-1; i>=0; i--)
00075         if (table[i].sourceIP == source &&
00076             table[i].destinationIP == destination &&
00077             table[i].flowId == flow)
00078             break;
00079 
00080     return i;
00081 }
00082 
00083 int FlowTable::find(nsaddr_t source, nsaddr_t destination, const Path &route) {
00084     register int i;
00085     for (i=size-1; i>=0; i--)
00086         if (table[i].sourceIP == source &&
00087             table[i].destinationIP == destination &&
00088             table[i].sourceRoute == route)
00089             break;
00090 
00091     return i;
00092 }
00093 
00094 void FlowTable::grow() {
00095     assert(0);
00096     TableEntry *temp;
00097     if (!(temp = new TableEntry[maxSize*2]))
00098         return;
00099     bcopy(table, temp, sizeof(TableEntry)*maxSize);
00100     delete table;
00101     maxSize *= 2;
00102     table = temp;
00103 }
00104 
00105 u_int16_t FlowTable::generateNextFlowId(nsaddr_t destination, bool allowDefault) {
00106     if ((counter&1)^allowDefault) // make sure parity is correct
00107         counter++;
00108 
00109     assert((counter & 1) == allowDefault);
00110     return counter++;
00111 }
00112 
00113 int FlowTable::createEntry(nsaddr_t source, nsaddr_t destination, 
00114                u_int16_t flow) {
00115     if (find(source, destination, flow) != -1)
00116         return -1;
00117     if (size == maxSize)
00118         grow();
00119     if (size == maxSize)
00120         return -1;
00121 
00122     table[size].sourceIP = source;
00123     table[size].destinationIP = destination;
00124     table[size].flowId = flow;
00125 
00126     if (flow & 1)
00127         DRTab.insert(source, destination, flow);
00128 
00129     return size++;
00130 }
00131 
00132 void FlowTable::noticeDeadLink(const ID &from, const ID &to) {
00133     double now = Scheduler::instance().clock();
00134 
00135     for (int i=0; i<size; i++)
00136         if (table[i].timeout >= now && table[i].sourceIP == net_addr)
00137             for (int n=0; n < (table[i].sourceRoute.length()-1); n++)
00138                 if (table[i].sourceRoute[n] == from &&
00139                     table[i].sourceRoute[n+1] == to) {
00140                     table[i].timeout = now - 1;
00141                     // XXX ych rediscover??? 5/2/01
00142                 }
00143 }
00144 
00145 // if ent represents a default flow, bad things are going down and we need
00146 // to rid the default flow table of them.
00147 static void checkDefaultFlow(DRTable &DRTab, const TableEntry &ent) {
00148     u_int16_t flow;
00149     if (!DRTab.find(ent.sourceIP, ent.destinationIP, flow))
00150         return;
00151     if (flow == ent.flowId)
00152         DRTab.flush(ent.sourceIP, ent.destinationIP);
00153 }
00154 
00155 void FlowTable::cleanup() {
00156     int front, back;
00157     double now = Scheduler::instance().clock();
00158 
00159     return; // it's messing up path orders...
00160 
00161     // init front to the first expired entry
00162     for (front=0; (front<size) && (table[front].timeout >= now); front++)
00163         ;
00164 
00165     // init back to the last unexpired entry
00166     for (back = size-1; (front<back) && (table[back].timeout < now); back--)
00167         checkDefaultFlow(DRTab, table[back]);
00168 
00169     while (front < back) {
00170         checkDefaultFlow(DRTab, table[front]);
00171         bcopy(table+back, table+front, sizeof(TableEntry)); // swap
00172         back--;
00173 
00174         // next expired entry
00175         while ((front<back) && (table[front].timeout >= now))
00176             front++;
00177         while ((front<back) && (table[back].timeout < now)) {
00178             checkDefaultFlow(DRTab, table[back]);
00179             back--;
00180         }
00181     }
00182 
00183     size = back+1;
00184 }
00185 
00186 void FlowTable::setNetAddr(nsaddr_t net_id) {
00187     net_addr = net_id;
00188 }
00189 
00190 bool FlowTable::defaultFlow(nsaddr_t source, nsaddr_t destination, 
00191                 u_int16_t &flow) {
00192     return DRTab.find(source, destination, flow);
00193 }
00194 
00195 DRTable::DRTable(int size_) {
00196     assert (size_ > 0);
00197     size = 0;
00198     maxSize = size_;
00199     table = new DRTabEnt[size_];
00200 }
00201 
00202 DRTable::~DRTable() {
00203     delete table;
00204 }
00205 
00206 bool DRTable::find(nsaddr_t src, nsaddr_t dst, u_int16_t &flow) {
00207     for (int i = 0; i < size; i++)
00208         if (src == table[i].src && dst == table[i].dst) {
00209             flow = table[i].fid;
00210             return true;
00211         }
00212     return false;
00213 }
00214 
00215 void DRTable::grow() {
00216     assert(0);
00217     DRTabEnt *temp;
00218     if (!(temp = new DRTabEnt[maxSize*2]))
00219         return;
00220     bcopy(table, temp, sizeof(DRTabEnt)*maxSize);
00221     delete table;
00222     maxSize *= 2;
00223     table = temp;
00224 }
00225 
00226 void DRTable::insert(nsaddr_t src, nsaddr_t dst, u_int16_t flow) {
00227     assert(flow & 1);
00228     for (int i = 0; i < size; i++) {
00229         if (src == table[i].src && dst == table[i].dst) {
00230             if ((short)((flow) - (table[i].fid)) > 0) {
00231                 table[i].fid = flow;
00232             } else {
00233             }
00234             return;
00235         }
00236     }
00237 
00238     if (size == maxSize)
00239         grow();
00240 
00241     assert(size != maxSize);
00242 
00243     table[size].src = src;
00244     table[size].dst = dst;
00245     table[size].fid = flow;
00246     size++;
00247 }
00248 
00249 void DRTable::flush(nsaddr_t src, nsaddr_t dst) {
00250     for (int i = 0; i < size; i++)
00251         if (src == table[i].src && dst == table[i].dst) {
00252             table[i].src = table[size-1].src;
00253             table[i].dst = table[size-1].dst;
00254             table[i].fid = table[size-1].fid;
00255             size--;
00256             return;
00257         }
00258     assert(0);
00259 }
00260 
00261 ARSTable::ARSTable(int size_) {
00262     size = size_;
00263     victim = 0;
00264     table = new ARSTabEnt[size_];
00265     bzero(table, sizeof(ARSTabEnt)*size_);
00266 }
00267 
00268 ARSTable::~ARSTable() {
00269     delete table;
00270 }
00271 
00272 void ARSTable::insert(int uid, u_int16_t fid, int hopsEarly) {
00273     int i = victim;
00274     assert(hopsEarly);
00275     
00276     do {
00277         if (!table[i].hopsEarly)
00278             break; // we found a victim
00279         i = (i+1)%size;
00280     } while (i != victim);
00281 
00282     if (table[i].hopsEarly) // full. need extreme measures.
00283         victim = (victim+1)%size;
00284 
00285     table[i].hopsEarly = hopsEarly;
00286     table[i].uid       = uid;
00287     table[i].fid       = fid;
00288 }
00289 
00290 int ARSTable::findAndClear(int uid, u_int16_t fid) {
00291     int i, retval;
00292 
00293     for (i=0; i<size; i++) {
00294             if (table[i].hopsEarly && table[i].uid == uid) {
00295                 if (table[i].fid == fid) {
00296                     retval = table[i].hopsEarly;
00297                 table[i].hopsEarly = 0;
00298                 return retval;
00299             } else {
00300                 table[i].hopsEarly = 0;
00301                 return 0;
00302             }
00303         }
00304     }
00305 
00306     return 0;
00307 }

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