INET Framework for OMNeT++/OMNEST
macTable.cc
Go to the documentation of this file.
00001 
00002 #include "macTable.h"
00003 
00004 Define_Module(MACTable);
00005 
00006 
00007 /* --- PUBLIC --- */
00008 
00009 MACTable::MACTable() {
00010   this->initDefaults();
00011   return;
00012 }
00013 
00014 MACTable::MACTable(int _tableSize) {
00015   this->initDefaults();
00016   if (_tableSize < 0) {
00017     this->addressTableSize = 0;
00018   } else {
00019     this->addressTableSize = _tableSize;
00020   }
00021   return;
00022 }
00023 
00024 MACTable::~MACTable() {
00025   return;
00026 }
00027 
00028 const MACTable::AddressTable * MACTable::getTable() {
00029   return &(this->table);
00030 }
00031 
00032 
00033 
00034 void MACTable::update(MACAddress& addr, int port) {
00035         Enter_Method_Silent();
00036 
00037     flushAged();
00038 
00039   AddressTable::iterator iter;
00040 
00041   iter = this->table.find(addr);
00042   if (iter == this->table.end()) {
00043     // Observe finite table size
00044     if (this->addressTableSize != 0 && this->table.size() == (unsigned int)addressTableSize) {
00045       EV << "Making room in Address Table by throwing out aged entries.\n";
00046 
00047       if (this->table.size() == (unsigned int)addressTableSize) {
00048         removeOldest();
00049       }
00050     }
00051     // Add entry to table
00052     EV << "Adding entry to Address Table: "<< addr << " --> port" << port << "\n";
00053 
00054     tRecord entry;
00055     entry.addr = addr;
00056     entry.insert_time = simTime();
00057     entry.portList.push_back(port);
00058     entry.type = DYNAMIC;
00059     entry.spec = NONE;
00060 
00061     this->table[addr] = entry;
00062   } else {
00063     // Update existing entry
00064     EV << "Updating entry in Address Table: "<< addr << " --> port" << port << "\n";
00065 
00066     tRecord& entry = iter->second;
00067 
00068     if (entry.type == DYNAMIC) {
00069                 entry.insert_time = simTime();
00070                 if (entry.portList.at(0) != port) {
00071                         entry.portList.clear();
00072                         entry.portList.push_back(port);
00073                 }
00074     }
00075   }
00076 
00077   return;
00078 }
00079 
00080 MACTable::tSpec MACTable::getSpec(MACAddress& addr) {
00081         Enter_Method_Silent();
00082 
00083     AddressTable::iterator iter = table.find(addr);
00084     if (iter == table.end()) {
00085         // not found
00086         return NONE;
00087     }
00088     if ((iter->second.type != STATIC) &&
00089         (iter->second.insert_time + agingTime) <= simTime()) {
00090         // don't use (and throw out) aged entries
00091         EV << "Ignoring and deleting aged entry: "<< iter->first << "\n";
00092 
00093         table.erase(iter);
00094 
00095         return NONE;
00096     }
00097 
00098     return iter->second.spec;
00099 }
00100 
00101 
00102 MACTable::tPortList& MACTable::getPorts(MACAddress& addr) {
00103 
00104         Enter_Method_Silent();
00105 
00106     AddressTable::iterator iter = table.find(addr);
00107     if (iter == table.end()) {
00108         // not found
00109         return empty;
00110     }
00111     if ((iter->second.type != STATIC) &&
00112         (iter->second.insert_time + agingTime) <= simTime()) {
00113         // don't use (and throw out) aged entries
00114         EV << "Ignoring and deleting aged entry: "<< iter->first << "\n";
00115 
00116         table.erase(iter);
00117 
00118         return empty;
00119     }
00120 
00121     return iter->second.portList;
00122 }
00123 
00124 void MACTable::flush() {
00125 
00126         Enter_Method_Silent();
00127 
00128         AddressTable::iterator iter;
00129         for (iter = table.begin(); iter != table.end();) {
00130                 AddressTable::iterator cur = iter++;
00131                 tRecord entry = cur->second;
00132                 if (entry.type == DYNAMIC) { //TODO GROUP adresses too ?
00133                         table.erase(cur);
00134                 }
00135         }
00136 
00137   return;
00138 }
00139 
00140 void MACTable::enableFasterAging() {
00141         Enter_Method_Silent();
00142         agingTime = fasterAging;
00143 }
00144 
00145 void MACTable::resetAging() {
00146         Enter_Method_Silent();
00147         agingTime = uAgingTime;
00148 }
00149 
00150 
00151 /* --- PRIVATE --- */
00152 
00153 
00154 void MACTable::initDefaults() {
00155   addressTableSize = 1024; // TODO
00156 
00157   /* by IEEE 802.1D-1998
00158    * " The Bridges then use a short value
00159    * to age out dynamic entries
00160    * in the Fitering Database for a period."
00161    * */
00162   fasterAging = 5; // short value to age out ... (5s < 5xHelloTime = 10s)
00163   uAgingTime = 300; // recommended value by IEEE 802.1D-1998 (and later)...
00164   agingTime = uAgingTime; // renew of user defined value, is triggered by STP process and receiving bpdu
00165   return;
00166 }
00167 
00168 /* MGMT */
00169 
00170 void MACTable::flushAged() {
00171 
00172         Enter_Method_Silent();
00173 
00174         AddressTable::iterator iter;
00175         for (iter = this->table.begin(); iter != this->table.end();) {
00176                 AddressTable::iterator cur = iter++; // iter will get invalidated after erase()
00177                 tRecord entry = cur->second;
00178                 if (entry.type == DYNAMIC && entry.insert_time + agingTime <= simTime()) {
00179                         EV << "Removing aged entry from Address Table: " << cur->first << "\n";
00180                         this->table.erase(cur);
00181                 }
00182         }
00183         return;
00184 }
00185 
00186 void MACTable::removeOldest() {
00187 
00188         Enter_Method_Silent();
00189 
00190         AddressTable::iterator oldest = this->table.end();
00191   simtime_t oldestInsertTime = simTime()+1;
00192   for (AddressTable::iterator iter = this->table.begin(); iter != this->table.end(); iter++) {
00193     if (iter->second.type != DYNAMIC && iter->second.insert_time < oldestInsertTime) {
00194       oldest = iter;
00195       oldestInsertTime = iter->second.insert_time;
00196     }
00197   }
00198   if (oldest != this->table.end()) {
00199     EV << "Table full, removing oldest entry: " <<
00200       oldest->first << "\n";
00201     this->table.erase(oldest);
00202   }
00203   return;
00204 }
00205 
00206 
00207 void MACTable::add(MACAddress addr, int port, tType type, tSpec spec) {
00208   AddressTable::iterator iter;
00209 
00210   iter = this->table.find(addr);
00211   if (iter == this->table.end()) { // record not found
00212         // Observe finite table size
00213         if (this->addressTableSize != 0 && this->table.size() == (unsigned int)addressTableSize) {
00214           EV << "Making room in Address Table by throwing out aged entries.\n";
00215 
00216           if (this->table.size() == (unsigned int)addressTableSize) {
00217                 removeOldest();
00218           }
00219         }
00220         // Add entry to table
00221         EV << "Adding entry to Address Table: "<< addr << " --> port" << port << "\n";
00222 
00223         tRecord entry; // create new entry, with given port & type
00224         entry.addr = addr;
00225         entry.insert_time = simTime();
00226         entry.portList.push_back(port);
00227         entry.type = type;
00228         entry.spec = spec;
00229 
00230         this->table[addr] = entry;
00231   } else {
00232         // Update existing entry
00233         EV << "Updating entry in Address Table: "<< addr << " --> port" << port << "\n";
00234 
00235         tRecord& entry = iter->second;
00236 
00237         entry.insert_time = simTime();
00238         unsigned int i;
00239         for (i = 0; i < entry.portList.size(); i++) { // search through portList for given port
00240                 if (entry.portList.at(i) == port) {
00241                         break;
00242                 }
00243         }
00244         if (i < entry.portList.size()) {
00245                 entry.portList.clear();
00246                 entry.portList.push_back(port);
00247         }
00248   }
00249 
00250   return;
00251 }
00252 
00253 void MACTable::remove(MACAddress addr) {
00254         AddressTable::iterator iter;
00255 
00256         iter = this->table.find(addr);
00257         if (iter == this->table.end()) { // record not found
00258           return;
00259         } else {
00260           this->table.erase(iter);
00261         }
00262         return;
00263 }
00264 
00265 void MACTable::removePort(MACAddress addr, int port) {
00266         AddressTable::iterator iter;
00267 
00268         iter = this->table.find(addr);
00269         if (iter == this->table.end()) { // record not found
00270           return;
00271         } else {
00272                 tRecord& entry = iter->second;
00273                 tPortList::iterator pIter;
00274                 for (pIter = entry.portList.begin(); pIter < entry.portList.end(); pIter++) { // search through portList for given port
00275                         if (*pIter == port) {
00276                                 entry.portList.erase(pIter);
00277                                 break;
00278                         }
00279                 }
00280         }
00281         return;
00282 }
00283 
00284 void MACTable::addStatic(MACAddress addr, tPortList ports) {
00285         AddressTable::iterator iter;
00286 
00287         iter = this->table.find(addr);
00288         if (iter == this->table.end()) { // record not found
00289         // Observe finite table size
00290         if (this->addressTableSize != 0 && this->table.size() == (unsigned int)addressTableSize) {
00291           EV << "Making room in Address Table by throwing out aged entries.\n";
00292 
00293           if (this->table.size() == (unsigned int)addressTableSize) {
00294                 removeOldest();
00295           }
00296         }
00297         // Add entry to table
00298         EV << "Adding static entry to Address Table: "<< addr << " " << ports << std::endl;
00299 
00300         tRecord entry; // create new entry, with given port & type
00301         entry.addr = addr;
00302         entry.insert_time = simTime();
00303         entry.portList = ports;
00304         entry.type = STATIC;
00305         entry.spec = NONE;
00306 
00307         this->table[addr] = entry;
00308         } else {
00309                 // Update existing entry
00310                 EV << "Updating entry in Address Table: "<< addr << " " << ports << std::endl;
00311 
00312                 tRecord& entry = iter->second;
00313 
00314                 entry.insert_time = simTime();
00315                 unsigned int i;
00316                 unsigned int c;
00317                 for(i = 0; i < ports.size(); i++) { // for all input port number
00318                         for(c = 0; c < entry.portList.size(); c++) { // search through whole port vector
00319                                 if (entry.portList.at(c) == ports.at(i)) { // if port number match
00320                                         break;
00321                                 }
00322 
00323                         }
00324                         if (c == entry.portList.size()) { // if port record not found
00325                                 entry.portList.push_back(ports.at(i)); // insert new
00326                         }
00327 
00328                 }
00329         }
00330 
00331 
00332         return;
00333 }
00334 
00335 
00336 /* --- PROTECTED --- */
00337 
00338 void MACTable::initialize() {
00339         this->initDefaults();
00340 
00341         /* TEST */
00342 /*
00343         tPortList tmp0, tmp1;
00344         tmp0.push_back(0);
00345         tmp0.push_back(1);
00346         tmp0.push_back(2);
00347         tmp0.push_back(3);
00348 
00349         tmp1.push_back(2);
00350         tmp1.push_back(3);
00351         tmp1.push_back(4);
00352         tmp1.push_back(5);
00353 
00354         addStatic(MACAddress("01:00:00:00:00:01"), tmp0);
00355         addStatic(MACAddress("01:00:00:00:00:02"), tmp1);
00356         removePort(MACAddress("01:00:00:00:00:01"), 2);
00357         remove(MACAddress("01:00:00:00:00:02"));
00358         add(MACAddress("01:00:00:00:00:03"), 16, GROUP, NONE);
00359 */
00360         /* END TEST */
00361 
00362 
00363         /* IEEE802.1D Table 7-10 Reserved addresses */
00364           // Bridge Group Address -> go to STP
00365         add(MACAddress("01-80-C2-00-00-00"), 0, STATIC, STP);
00366         /* end of table */
00367 
00368 
00369         WATCH_MAP(this->table);
00370         WATCH(this->addressTableSize);
00371         WATCH(this->agingTime);
00372         WATCH_RW(uAgingTime);
00373         return;
00374 }
00375 
00376 void MACTable::finish() {
00377         EV << "ANSA Switch, end of transmission." << std::endl;
00378         return;
00379 }
00380 
00381 
00382