#include <MACRelayUnitBase.h>
Inheritance diagram for MACRelayUnitBase:
Protected Types | |
typedef std::map< MACAddress, AddressEntry, MAC_compare > | AddressTable |
Protected Member Functions | |
void | initialize () |
void | handleAndDispatchFrame (EtherFrame *frame, int inputport) |
void | broadcastFrame (EtherFrame *frame, int inputport) |
void | readAddressTable (const char *fileName) |
void | updateTableWithAddress (MACAddress &address, int portno) |
int | getPortForAddress (MACAddress &address) |
void | printAddressTable () |
void | removeAgedEntriesFromTable () |
void | removeOldestTableEntry () |
void | sendPauseFrame (int portno, int pauseUnits) |
Protected Attributes | |
int | numPorts |
int | addressTableSize |
simtime_t | agingTime |
AddressTable | addresstable |
int | seqNum |
Classes | |
struct | AddressEntry |
struct | MAC_compare |
typedef std::map<MACAddress, AddressEntry, MAC_compare> MACRelayUnitBase::AddressTable [protected] |
void MACRelayUnitBase::broadcastFrame | ( | EtherFrame * | frame, | |
int | inputport | |||
) | [protected] |
Utility function: sends the frame on all ports except inputport. The message pointer should not be referenced any more after this call.
00108 { 00109 for (int i=0; i<numPorts; ++i) 00110 if (i!=inputport) 00111 send((EtherFrame*)frame->dup(), "lowerLayerOut", i); 00112 delete frame; 00113 }
int MACRelayUnitBase::getPortForAddress | ( | MACAddress & | address | ) | [protected] |
Returns output port for address, or -1 if unknown.
00197 { 00198 AddressTable::iterator iter = addresstable.find(address); 00199 if (iter == addresstable.end()) 00200 { 00201 // not found 00202 return -1; 00203 } 00204 if (iter->second.insertionTime + agingTime <= simTime()) 00205 { 00206 // don't use (and throw out) aged entries 00207 EV << "Ignoring and deleting aged entry: "<< iter->first << " --> port" << iter->second.portno << "\n"; 00208 addresstable.erase(iter); 00209 return -1; 00210 } 00211 return iter->second.portno; 00212 }
void MACRelayUnitBase::handleAndDispatchFrame | ( | EtherFrame * | frame, | |
int | inputport | |||
) | [protected] |
Updates address table with source address, determines output port and sends out (or broadcasts) frame on ports. Includes calls to updateTableWithAddress() and getPortForAddress().
The message pointer should not be referenced any more after this call.
00073 { 00074 // update address table 00075 updateTableWithAddress(frame->getSrc(), inputport); 00076 00077 // handle broadcast frames first 00078 if (frame->getDest().isBroadcast()) 00079 { 00080 EV << "Broadcasting broadcast frame " << frame << endl; 00081 broadcastFrame(frame, inputport); 00082 return; 00083 } 00084 00085 // Finds output port of destination address and sends to output port 00086 // if not found then broadcasts to all other ports instead 00087 int outputport = getPortForAddress(frame->getDest()); 00088 if (inputport==outputport) 00089 { 00090 EV << "Output port is same as input port, " << frame->fullName() << 00091 " dest " << frame->getDest() << ", discarding frame\n"; 00092 delete frame; 00093 return; 00094 } 00095 if (outputport>=0) 00096 { 00097 EV << "Sending frame " << frame << " with dest address " << frame->getDest() << " to port " << outputport << endl; 00098 send(frame, "lowerLayerOut", outputport); 00099 } 00100 else 00101 { 00102 EV << "Dest address " << frame->getDest() << " unknown, broadcasting frame " << frame << endl; 00103 broadcastFrame(frame, inputport); 00104 } 00105 }
void MACRelayUnitBase::initialize | ( | ) | [protected] |
Read parameters parameters.
Reimplemented in MACRelayUnitNP, and MACRelayUnitPP.
00049 { 00050 // number of ports 00051 numPorts = gate("lowerLayerOut",0)->size(); 00052 if (gate("lowerLayerIn",0)->size()!=numPorts) 00053 error("the sizes of the lowerLayerIn[] and lowerLayerOut[] gate vectors must be the same"); 00054 00055 // other parameters 00056 addressTableSize = par("addressTableSize"); 00057 addressTableSize = addressTableSize >= 0 ? addressTableSize : 0; 00058 00059 agingTime = par("agingTime"); 00060 agingTime = agingTime > 0 ? agingTime : 10; 00061 00062 // Option to pre-read in Address Table. To turn ot off, set addressTableFile to empty string 00063 const char *addressTableFile = par("addressTableFile"); 00064 if (addressTableFile && *addressTableFile) 00065 readAddressTable(addressTableFile); 00066 00067 seqNum = 0; 00068 00069 WATCH_MAP(addresstable); 00070 }
void MACRelayUnitBase::printAddressTable | ( | ) | [protected] |
Prints contents of address table on ev.
00116 { 00117 AddressTable::iterator iter; 00118 EV << "Address Table (" << addresstable.size() << " entries):\n"; 00119 for (iter = addresstable.begin(); iter!=addresstable.end(); ++iter) 00120 { 00121 EV << " " << iter->first << " --> port" << iter->second.portno << 00122 (iter->second.insertionTime+agingTime <= simTime() ? " (aged)" : "") << endl; 00123 } 00124 }
void MACRelayUnitBase::readAddressTable | ( | const char * | fileName | ) | [protected] |
Pre-reads in entries for Address Table during initialization.
00216 { 00217 FILE *fp = fopen(fileName, "r"); 00218 if (fp == NULL) 00219 error("cannot open address table file `%s'", fileName); 00220 00221 // Syntax of the file goes as: 00222 // Address in hexadecimal representation, Portno 00223 // ffffffff 1 00224 // ffffeed1 2 00225 // aabcdeff 3 00226 // 00227 // etc... 00228 // 00229 // Each iteration of the loop reads in an entire line i.e. up to '\n' or EOF characters 00230 // and uses strtok to extract tokens from the resulting string 00231 char *line; 00232 int lineno = 0; 00233 while ((line = fgetline(fp)) != NULL) 00234 { 00235 lineno++; 00236 00237 // lines beginning with '#' are treated as comments 00238 if (line[0]=='#') 00239 continue; 00240 00241 // scan in hexaddress 00242 char *hexaddress = strtok(line, " \t"); 00243 // scan in port number 00244 char *portno = strtok(NULL, " \t"); 00245 00246 // empty line? 00247 if (!hexaddress) 00248 continue; 00249 00250 // broken line? 00251 if (!portno) 00252 error("line %d invalid in address table file `%s'", lineno, fileName); 00253 00254 // Create an entry with address and portno and insert into table 00255 AddressEntry entry; 00256 entry.insertionTime = 0; 00257 entry.portno = atoi(portno); 00258 addresstable[MACAddress(hexaddress)] = entry; 00259 00260 // Garbage collection before next iteration 00261 delete [] line; 00262 } 00263 fclose(fp); 00264 }
void MACRelayUnitBase::removeAgedEntriesFromTable | ( | ) | [protected] |
Utility function: throws out all aged entries from table.
00127 { 00128 for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end();) 00129 { 00130 AddressTable::iterator cur = iter++; // iter will get invalidated after erase() 00131 AddressEntry& entry = cur->second; 00132 if (entry.insertionTime + agingTime <= simTime()) 00133 { 00134 EV << "Removing aged entry from Address Table: " << 00135 cur->first << " --> port" << cur->second.portno << "\n"; 00136 addresstable.erase(cur); 00137 } 00138 } 00139 }
void MACRelayUnitBase::removeOldestTableEntry | ( | ) | [protected] |
Utility function: throws out oldest (not necessarily aged) entry from table.
00142 { 00143 AddressTable::iterator oldest = addresstable.end(); 00144 simtime_t oldestInsertTime = simTime()+1; 00145 for (AddressTable::iterator iter = addresstable.begin(); iter != addresstable.end(); iter++) 00146 { 00147 if (iter->second.insertionTime < oldestInsertTime) 00148 { 00149 oldest = iter; 00150 oldestInsertTime = iter->second.insertionTime; 00151 } 00152 } 00153 if (oldest != addresstable.end()) 00154 { 00155 EV << "Table full, removing oldest entry: " << 00156 oldest->first << " --> port" << oldest->second.portno << "\n"; 00157 addresstable.erase(oldest); 00158 } 00159 }
void MACRelayUnitBase::sendPauseFrame | ( | int | portno, | |
int | pauseUnits | |||
) | [protected] |
Utility function (for use by subclasses) to send a flow control PAUSE frame on the given port.
00268 { 00269 EV << "Creating and sending PAUSE frame on port " << portno << " with duration=" << pauseUnits << " units\n"; 00270 00271 // create Ethernet frame 00272 char framename[40]; 00273 sprintf(framename, "pause-%d-%d", id(), seqNum++); 00274 EtherPauseFrame *frame = new EtherPauseFrame(framename, ETH_PAUSE); 00275 frame->setPauseTime(pauseUnits); 00276 00277 frame->setByteLength(ETHER_MAC_FRAME_BYTES+ETHER_PAUSE_COMMAND_BYTES); 00278 if (frame->byteLength() < MIN_ETHERNET_FRAME) 00279 frame->setByteLength(MIN_ETHERNET_FRAME); 00280 00281 send(frame, "lowerLayerOut", portno); 00282 }
void MACRelayUnitBase::updateTableWithAddress | ( | MACAddress & | address, | |
int | portno | |||
) | [protected] |
Enters address into table.
00162 { 00163 AddressTable::iterator iter; 00164 00165 iter = addresstable.find(address); 00166 if (iter == addresstable.end()) 00167 { 00168 // Observe finite table size 00169 if (addressTableSize!=0 && addresstable.size() == (unsigned int)addressTableSize) 00170 { 00171 // lazy removal of aged entries: only if table gets full (this step is not strictly needed) 00172 EV << "Making room in Address Table by throwing out aged entries.\n"; 00173 removeAgedEntriesFromTable(); 00174 00175 if (addresstable.size() == (unsigned int)addressTableSize) 00176 removeOldestTableEntry(); 00177 } 00178 00179 // Add entry to table 00180 EV << "Adding entry to Address Table: "<< address << " --> port" << portno << "\n"; 00181 AddressEntry entry; 00182 entry.portno = portno; 00183 entry.insertionTime = simTime(); 00184 addresstable[address] = entry; 00185 } 00186 else 00187 { 00188 // Update existing entry 00189 EV << "Updating entry in Address Table: "<< address << " --> port" << portno << "\n"; 00190 AddressEntry& entry = iter->second; 00191 entry.insertionTime = simTime(); 00192 entry.portno = portno; 00193 } 00194 }
AddressTable MACRelayUnitBase::addresstable [protected] |
int MACRelayUnitBase::addressTableSize [protected] |
simtime_t MACRelayUnitBase::agingTime [protected] |
int MACRelayUnitBase::numPorts [protected] |
int MACRelayUnitBase::seqNum [protected] |