#include <ARP.h>
typedef std::map<IPAddress, ARPCacheEntry*> ARP::ARPCache |
typedef std::vector<cMessage*> ARP::MsgPtrVector |
ARP::~ARP | ( | ) |
bool ARP::addressRecognized | ( | IPAddress | destAddr, | |
InterfaceEntry * | ie | |||
) | [protected] |
00315 { 00316 if (rt->localDeliver(destAddr)) 00317 return true; 00318 00319 // respond to Proxy ARP request: if we can route this packet (and the 00320 // output port is different from this one), say yes 00321 if (!doProxyARP) 00322 return false; 00323 InterfaceEntry *rtie = rt->interfaceForDestAddr(destAddr); 00324 return rtie!=NULL && rtie!=ie; 00325 }
void ARP::dumpARPPacket | ( | ARPPacket * | arp | ) | [protected] |
00328 { 00329 EV << (arp->getOpcode()==ARP_REQUEST ? "ARP_REQ" : arp->getOpcode()==ARP_REPLY ? "ARP_REPLY" : "unknown type") 00330 << " src=" << arp->getSrcIPAddress() << " / " << arp->getSrcMACAddress() 00331 << " dest=" << arp->getDestIPAddress() << " / " << arp->getDestMACAddress() << "\n"; 00332 }
void ARP::finish | ( | ) | [protected, virtual] |
00067 { 00068 recordScalar("ARP requests sent", numRequestsSent); 00069 recordScalar("ARP replies sent", numRepliesSent); 00070 recordScalar("ARP resolutions", numResolutions); 00071 recordScalar("failed ARP resolutions", numFailedResolutions); 00072 }
void ARP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
00085 { 00086 if (msg->isSelfMessage()) 00087 { 00088 requestTimedOut(msg); 00089 } 00090 else if (dynamic_cast<ARPPacket *>(msg)) 00091 { 00092 ARPPacket *arp = (ARPPacket *)msg; 00093 processARPPacket(arp); 00094 } 00095 else // not ARP 00096 { 00097 processOutboundPacket(msg); 00098 } 00099 if (ev.isGUI()) 00100 updateDisplayString(); 00101 }
void ARP::initialize | ( | ) | [protected, virtual] |
00044 { 00045 ift = InterfaceTableAccess().get(); 00046 rt = RoutingTableAccess().get(); 00047 00048 retryTimeout = par("retryTimeout"); 00049 retryCount = par("retryCount"); 00050 cacheTimeout = par("cacheTimeout"); 00051 doProxyARP = par("proxyARP"); 00052 00053 pendingQueue.setName("pendingQueue"); 00054 00055 // init statistics 00056 numRequestsSent = numRepliesSent = 0; 00057 numResolutions = numFailedResolutions = 0; 00058 WATCH(numRequestsSent); 00059 WATCH(numRepliesSent); 00060 WATCH(numResolutions); 00061 WATCH(numFailedResolutions); 00062 00063 WATCH_PTRMAP(arpCache); 00064 }
void ARP::initiateARPResolution | ( | ARPCacheEntry * | entry | ) | [protected] |
00226 { 00227 IPAddress nextHopAddr = entry->myIter->first; 00228 entry->pending = true; 00229 entry->numRetries = 0; 00230 entry->lastUpdate = 0; 00231 sendARPRequest(entry->ie, nextHopAddr); 00232 00233 // start timer 00234 cMessage *msg = entry->timer = new cMessage("ARP timeout"); 00235 msg->setContextPointer(entry); 00236 scheduleAt(simTime()+retryTimeout, msg); 00237 00238 numResolutions++; 00239 }
void ARP::processARPPacket | ( | ARPPacket * | arp | ) | [protected] |
00336 { 00337 EV << "ARP packet " << arp << " arrived:\n"; 00338 dumpARPPacket(arp); 00339 00340 // extract input port 00341 IPRoutingDecision *controlInfo = check_and_cast<IPRoutingDecision*>(arp->removeControlInfo()); 00342 InterfaceEntry *ie = ift->interfaceAt(controlInfo->interfaceId()); 00343 delete controlInfo; 00344 00345 // 00346 // Recipe a'la RFC 826: 00347 // 00348 // ?Do I have the hardware type in ar$hrd? 00349 // Yes: (almost definitely) 00350 // [optionally check the hardware length ar$hln] 00351 // ?Do I speak the protocol in ar$pro? 00352 // Yes: 00353 // [optionally check the protocol length ar$pln] 00354 // Merge_flag := false 00355 // If the pair <protocol type, sender protocol address> is 00356 // already in my translation table, update the sender 00357 // hardware address field of the entry with the new 00358 // information in the packet and set Merge_flag to true. 00359 // ?Am I the target protocol address? 00360 // Yes: 00361 // If Merge_flag is false, add the triplet <protocol type, 00362 // sender protocol address, sender hardware address> to 00363 // the translation table. 00364 // ?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!) 00365 // Yes: 00366 // Swap hardware and protocol fields, putting the local 00367 // hardware and protocol addresses in the sender fields. 00368 // Set the ar$op field to ares_op$REPLY 00369 // Send the packet to the (new) target hardware address on 00370 // the same hardware on which the request was received. 00371 // 00372 00373 MACAddress srcMACAddress = arp->getSrcMACAddress(); 00374 IPAddress srcIPAddress = arp->getSrcIPAddress(); 00375 00376 if (srcMACAddress.isUnspecified()) 00377 error("wrong ARP packet: source MAC address is empty"); 00378 if (srcIPAddress.isUnspecified()) 00379 error("wrong ARP packet: source IP address is empty"); 00380 00381 bool mergeFlag = false; 00382 // "If ... sender protocol address is already in my translation table" 00383 ARPCache::iterator it = arpCache.find(srcIPAddress); 00384 if (it!=arpCache.end()) 00385 { 00386 // "update the sender hardware address field" 00387 ARPCacheEntry *entry = (*it).second; 00388 updateARPCache(entry, srcMACAddress); 00389 mergeFlag = true; 00390 } 00391 00392 // "?Am I the target protocol address?" 00393 // if Proxy ARP is enabled, we also have to reply if we're a router to the dest IP address 00394 if (addressRecognized(arp->getDestIPAddress(), ie)) 00395 { 00396 // "If Merge_flag is false, add the triplet protocol type, sender 00397 // protocol address, sender hardware address to the translation table" 00398 if (!mergeFlag) 00399 { 00400 ARPCacheEntry *entry; 00401 if (it!=arpCache.end()) 00402 { 00403 entry = (*it).second; 00404 } 00405 else 00406 { 00407 entry = new ARPCacheEntry(); 00408 ARPCache::iterator where = arpCache.insert(arpCache.begin(), std::make_pair(srcIPAddress,entry)); 00409 entry->myIter = where; 00410 entry->ie = ie; 00411 00412 entry->pending = false; 00413 entry->timer = NULL; 00414 entry->numRetries = 0; 00415 } 00416 updateARPCache(entry, srcMACAddress); 00417 } 00418 00419 // "?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!)" 00420 switch (arp->getOpcode()) 00421 { 00422 case ARP_REQUEST: 00423 { 00424 EV << "Packet was ARP REQUEST, sending REPLY\n"; 00425 00426 // find our own IP address and MAC address on the given interface 00427 MACAddress myMACAddress = ie->macAddress(); 00428 IPAddress myIPAddress = ie->ipv4()->inetAddress(); 00429 00430 // "Swap hardware and protocol fields", etc. 00431 arp->setName("arpREPLY"); 00432 IPAddress origDestAddress = arp->getDestIPAddress(); 00433 arp->setDestIPAddress(srcIPAddress); 00434 arp->setDestMACAddress(srcMACAddress); 00435 arp->setSrcIPAddress(origDestAddress); 00436 arp->setSrcMACAddress(myMACAddress); 00437 arp->setOpcode(ARP_REPLY); 00438 delete arp->removeControlInfo(); 00439 sendPacketToNIC(arp, ie, srcMACAddress); 00440 numRepliesSent++; 00441 break; 00442 } 00443 case ARP_REPLY: 00444 { 00445 EV << "Discarding packet\n"; 00446 delete arp; 00447 break; 00448 } 00449 case ARP_RARP_REQUEST: error("RARP request received: RARP is not supported"); 00450 case ARP_RARP_REPLY: error("RARP reply received: RARP is not supported"); 00451 default: error("Unsupported opcode %d in received ARP packet",arp->getOpcode()); 00452 } 00453 } 00454 else 00455 { 00456 // address not recognized 00457 EV << "IP address " << arp->getDestIPAddress() << " not recognized, dropping ARP packet\n"; 00458 delete arp; 00459 } 00460 }
void ARP::processOutboundPacket | ( | cMessage * | msg | ) | [protected] |
00112 { 00113 EV << "Packet " << msg << " arrived from higher layer, "; 00114 00115 // get next hop address from control info in packet 00116 IPRoutingDecision *controlInfo = check_and_cast<IPRoutingDecision*>(msg->removeControlInfo()); 00117 IPAddress nextHopAddr = controlInfo->nextHopAddr(); 00118 InterfaceEntry *ie = ift->interfaceAt(controlInfo->interfaceId()); 00119 delete controlInfo; 00120 00121 // if output interface is not broadcast, don't bother with ARP 00122 if (!ie->isBroadcast()) 00123 { 00124 EV << "output interface " << ie->name() << " is not broadcast, skipping ARP\n"; 00125 #ifdef _MAX_SPEED 00126 sendDirect(msg, 0, parentModule(), "ifOut", ie->networkLayerGateIndex()); 00127 #else 00128 send(msg, "nicOut", ie->networkLayerGateIndex()); 00129 #endif 00130 return; 00131 } 00132 00133 // determine what address to look up in ARP cache 00134 if (!nextHopAddr.isUnspecified()) 00135 { 00136 EV << "using next-hop address " << nextHopAddr << "\n"; 00137 } 00138 else 00139 { 00140 // try proxy ARP 00141 IPDatagram *datagram = check_and_cast<IPDatagram *>(msg); 00142 nextHopAddr = datagram->destAddress(); 00143 EV << "no next-hop address, using destination address " << nextHopAddr << " (proxy ARP)\n"; 00144 } 00145 00146 // 00147 // Handle multicast IP addresses. RFC 1112, section 6.4 says: 00148 // "An IP host group address is mapped to an Ethernet multicast address 00149 // by placing the low-order 23 bits of the IP address into the low-order 00150 // 23 bits of the Ethernet multicast address 01-00-5E-00-00-00 (hex). 00151 // Because there are 28 significant bits in an IP host group address, 00152 // more than one host group address may map to the same Ethernet multicast 00153 // address." 00154 // 00155 if (nextHopAddr.isMulticast()) 00156 { 00157 // FIXME: we do a simpler solution right now: send to the Broadcast MAC address 00158 EV << "destination address is multicast, sending packet to broadcast MAC address\n"; 00159 static MACAddress broadcastAddr("FF:FF:FF:FF:FF:FF"); 00160 sendPacketToNIC(msg, ie, broadcastAddr); 00161 return; 00162 #if 0 00163 // experimental RFC 1112 code 00164 // TBD needs counterpart to be implemented in EtherMAC processReceivedDataFrame(). 00165 unsigned char macBytes[6]; 00166 macBytes[0] = 0x01; 00167 macBytes[1] = 0x00; 00168 macBytes[2] = 0x5e; 00169 macBytes[3] = nextHopAddr.getDByte(1) & 0x7f; 00170 macBytes[4] = nextHopAddr.getDByte(2); 00171 macBytes[5] = nextHopAddr.getDByte(3); 00172 MACAddress multicastMacAddr; 00173 multicastMacAddr.setAddressBytes(bytes); 00174 sendPacketToNIC(msg, ie, multicastMacAddr); 00175 return; 00176 #endif 00177 } 00178 00179 // try look up 00180 ARPCache::iterator it = arpCache.find(nextHopAddr); 00181 //ASSERT(it==arpCache.end() || ie==(*it).second->ie); // verify: if arpCache gets keyed on InterfaceEntry* too, this becomes unnecessary 00182 if (it==arpCache.end()) 00183 { 00184 // no cache entry: launch ARP request 00185 ARPCacheEntry *entry = new ARPCacheEntry(); 00186 ARPCache::iterator where = arpCache.insert(arpCache.begin(), std::make_pair(nextHopAddr,entry)); 00187 entry->myIter = where; // note: "inserting a new element into a map does not invalidate iterators that point to existing elements" 00188 entry->ie = ie; 00189 00190 EV << "Starting ARP resolution for " << nextHopAddr << "\n"; 00191 initiateARPResolution(entry); 00192 00193 // and queue up packet 00194 entry->pendingPackets.push_back(msg); 00195 pendingQueue.insert(msg); 00196 } 00197 else if ((*it).second->pending) 00198 { 00199 // an ARP request is already pending for this address -- just queue up packet 00200 EV << "ARP resolution for " << nextHopAddr << " is pending, queueing up packet\n"; 00201 (*it).second->pendingPackets.push_back(msg); 00202 pendingQueue.insert(msg); 00203 } 00204 else if ((*it).second->lastUpdate+cacheTimeout<simTime()) 00205 { 00206 EV << "ARP cache entry for " << nextHopAddr << " expired, starting new ARP resolution\n"; 00207 00208 // cache entry stale, send new ARP request 00209 ARPCacheEntry *entry = (*it).second; 00210 entry->ie = ie; // routing table may have changed 00211 initiateARPResolution(entry); 00212 00213 // and queue up packet 00214 entry->pendingPackets.push_back(msg); 00215 pendingQueue.insert(msg); 00216 } 00217 else 00218 { 00219 // valid ARP cache entry found, flag msg with MAC address and send it out 00220 EV << "ARP cache hit, MAC address for " << nextHopAddr << " is " << (*it).second->macAddress << ", sending packet down\n"; 00221 sendPacketToNIC(msg, ie, (*it).second->macAddress); 00222 } 00223 }
void ARP::requestTimedOut | ( | cMessage * | selfmsg | ) | [protected] |
00280 { 00281 ARPCacheEntry *entry = (ARPCacheEntry *)selfmsg->contextPointer(); 00282 entry->numRetries++; 00283 if (entry->numRetries < retryCount) 00284 { 00285 // retry 00286 IPAddress nextHopAddr = entry->myIter->first; 00287 EV << "ARP request for " << nextHopAddr << " timed out, resending\n"; 00288 sendARPRequest(entry->ie, nextHopAddr); 00289 scheduleAt(simTime()+retryTimeout, selfmsg); 00290 return; 00291 } 00292 00293 // max retry count reached: ARP failure. 00294 // throw out entry from cache, delete pending messages 00295 MsgPtrVector& pendingPackets = entry->pendingPackets; 00296 EV << "ARP timeout, max retry count " << retryCount << " for " 00297 << entry->myIter->first << " reached. Dropping " << pendingPackets.size() 00298 << " waiting packets from the queue\n"; 00299 while (!pendingPackets.empty()) 00300 { 00301 MsgPtrVector::iterator i = pendingPackets.begin(); 00302 cMessage *msg = (*i); 00303 pendingPackets.erase(i); 00304 pendingQueue.remove(msg); 00305 delete msg; 00306 } 00307 delete selfmsg; 00308 arpCache.erase(entry->myIter); 00309 delete entry; 00310 numFailedResolutions++; 00311 }
void ARP::sendARPRequest | ( | InterfaceEntry * | ie, | |
IPAddress | ipAddress | |||
) | [protected] |
00257 { 00258 // find our own IP address and MAC address on the given interface 00259 MACAddress myMACAddress = ie->macAddress(); 00260 IPAddress myIPAddress = ie->ipv4()->inetAddress(); 00261 00262 // both must be set 00263 ASSERT(!myMACAddress.isUnspecified()); 00264 ASSERT(!myIPAddress.isUnspecified()); 00265 00266 // fill out everything in ARP Request packet except dest MAC address 00267 ARPPacket *arp = new ARPPacket("arpREQ"); 00268 arp->setByteLength(ARP_HEADER_BYTES); 00269 arp->setOpcode(ARP_REQUEST); 00270 arp->setSrcMACAddress(myMACAddress); 00271 arp->setSrcIPAddress(myIPAddress); 00272 arp->setDestIPAddress(ipAddress); 00273 00274 static MACAddress broadcastAddress("ff:ff:ff:ff:ff:ff"); 00275 sendPacketToNIC(arp, ie, broadcastAddress); 00276 numRequestsSent++; 00277 }
void ARP::sendPacketToNIC | ( | cMessage * | msg, | |
InterfaceEntry * | ie, | |||
const MACAddress & | macAddress | |||
) | [protected] |
00242 { 00243 // add control info with MAC address 00244 Ieee802Ctrl *controlInfo = new Ieee802Ctrl(); 00245 controlInfo->setDest(macAddress); 00246 msg->setControlInfo(controlInfo); 00247 00248 // send out 00249 #ifdef _MAX_SPEED 00250 sendDirect(msg, 0, parentModule(), "ifOut", ie->networkLayerGateIndex()); 00251 #else 00252 send(msg, "nicOut", ie->networkLayerGateIndex()); 00253 #endif 00254 }
void ARP::updateARPCache | ( | ARPCacheEntry * | entry, | |
const MACAddress & | macAddress | |||
) | [protected] |
00463 { 00464 EV << "Updating ARP cache entry: " << entry->myIter->first << " <--> " << macAddress << "\n"; 00465 00466 // update entry 00467 if (entry->pending) 00468 { 00469 entry->pending = false; 00470 delete cancelEvent(entry->timer); 00471 entry->timer = NULL; 00472 entry->numRetries = 0; 00473 } 00474 entry->macAddress = macAddress; 00475 entry->lastUpdate = simTime(); 00476 00477 // process queued packets 00478 MsgPtrVector& pendingPackets = entry->pendingPackets; 00479 while (!pendingPackets.empty()) 00480 { 00481 MsgPtrVector::iterator i = pendingPackets.begin(); 00482 cMessage *msg = (*i); 00483 pendingPackets.erase(i); 00484 pendingQueue.remove(msg); 00485 EV << "Sending out queued packet " << msg << "\n"; 00486 sendPacketToNIC(msg, entry->ie, macAddress); 00487 } 00488 }
void ARP::updateDisplayString | ( | ) | [protected] |
00104 { 00105 char buf[80]; 00106 sprintf(buf, "%d cache entries\nsent req:%ld repl:%ld fail:%ld", 00107 arpCache.size(), numRequestsSent, numRepliesSent, numFailedResolutions); 00108 displayString().setTagArg("t",0,buf); 00109 }
ARPCache ARP::arpCache [protected] |
simtime_t ARP::cacheTimeout [protected] |
bool ARP::doProxyARP [protected] |
InterfaceTable* ARP::ift [protected] |
long ARP::numFailedResolutions [protected] |
long ARP::numRepliesSent [protected] |
long ARP::numRequestsSent [protected] |
long ARP::numResolutions [protected] |
cQueue ARP::pendingQueue [protected] |
int ARP::retryCount [protected] |
simtime_t ARP::retryTimeout [protected] |
RoutingTable* ARP::rt [protected] |