00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ARP.h"
00020 #include "IPv4InterfaceData.h"
00021 #include "Ieee802Ctrl_m.h"
00022
00023
00024 static std::ostream& operator<< (std::ostream& out, cMessage *msg)
00025 {
00026 out << "(" << msg->getClassName() << ")" << msg->getFullName();
00027 return out;
00028 }
00029
00030 static std::ostream& operator<< (std::ostream& out, const ARP::ARPCacheEntry& e)
00031 {
00032 if (e.pending)
00033 out << "pending (" << e.numRetries << " retries)";
00034 else
00035 out << "MAC:" << e.macAddress << " age:" << floor(simTime()-e.lastUpdate) << "s";
00036 return out;
00037 }
00038
00039
00040 Define_Module (ARP);
00041
00042 void ARP::initialize()
00043 {
00044 ift = InterfaceTableAccess().get();
00045 rt = RoutingTableAccess().get();
00046
00047 nicOutBaseGateId = gateSize("nicOut")==0 ? -1 : gate("nicOut",0)->getId();
00048
00049 retryTimeout = par("retryTimeout");
00050 retryCount = par("retryCount");
00051 cacheTimeout = par("cacheTimeout");
00052 doProxyARP = par("proxyARP");
00053
00054 pendingQueue.setName("pendingQueue");
00055
00056
00057 numRequestsSent = numRepliesSent = 0;
00058 numResolutions = numFailedResolutions = 0;
00059 WATCH(numRequestsSent);
00060 WATCH(numRepliesSent);
00061 WATCH(numResolutions);
00062 WATCH(numFailedResolutions);
00063
00064 WATCH_PTRMAP(arpCache);
00065 }
00066
00067 void ARP::finish()
00068 {
00069 recordScalar("ARP requests sent", numRequestsSent);
00070 recordScalar("ARP replies sent", numRepliesSent);
00071 recordScalar("ARP resolutions", numResolutions);
00072 recordScalar("failed ARP resolutions", numFailedResolutions);
00073 }
00074
00075 ARP::~ARP()
00076 {
00077 while (!arpCache.empty())
00078 {
00079 ARPCache::iterator i = arpCache.begin();
00080 delete (*i).second;
00081 arpCache.erase(i);
00082 }
00083 }
00084
00085 void ARP::handleMessage(cMessage *msg)
00086 {
00087 if (msg->isSelfMessage())
00088 {
00089 requestTimedOut(msg);
00090 }
00091 else if (dynamic_cast<ARPPacket *>(msg))
00092 {
00093 ARPPacket *arp = (ARPPacket *)msg;
00094 processARPPacket(arp);
00095 }
00096 else
00097 {
00098 processOutboundPacket(msg);
00099 }
00100 if (ev.isGUI())
00101 updateDisplayString();
00102 }
00103
00104 void ARP::updateDisplayString()
00105 {
00106 std::stringstream os;
00107
00108 os << arpCache.size() << " cache entries\nsent req:" << numRequestsSent
00109 << " repl:" << numRepliesSent << " fail:" << numFailedResolutions;
00110 getDisplayString().setTagArg("t", 0, os.str().c_str());
00111 }
00112
00113 void ARP::processOutboundPacket(cMessage *msg)
00114 {
00115 EV << "Packet " << msg << " arrived from higher layer, ";
00116
00117
00118 IPRoutingDecision *controlInfo = check_and_cast<IPRoutingDecision*>(msg->removeControlInfo());
00119 IPAddress nextHopAddr = controlInfo->getNextHopAddr();
00120 InterfaceEntry *ie = ift->getInterfaceById(controlInfo->getInterfaceId());
00121 delete controlInfo;
00122
00123
00124 if (!ie->isBroadcast())
00125 {
00126 EV << "output interface " << ie->getName() << " is not broadcast, skipping ARP\n";
00127 send(msg, nicOutBaseGateId + ie->getNetworkLayerGateIndex());
00128 return;
00129 }
00130
00131
00132 if (!nextHopAddr.isUnspecified())
00133 {
00134 EV << "using next-hop address " << nextHopAddr << "\n";
00135 }
00136 else
00137 {
00138
00139 IPDatagram *datagram = check_and_cast<IPDatagram *>(msg);
00140 nextHopAddr = datagram->getDestAddress();
00141 EV << "no next-hop address, using destination address " << nextHopAddr << " (proxy ARP)\n";
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 if (nextHopAddr.isMulticast())
00154 {
00155
00156 EV << "destination address is multicast, sending packet to broadcast MAC address\n";
00157 static MACAddress broadcastAddr("FF:FF:FF:FF:FF:FF");
00158 sendPacketToNIC(msg, ie, broadcastAddr);
00159 return;
00160 #if 0
00161
00162
00163 unsigned char macBytes[6];
00164 macBytes[0] = 0x01;
00165 macBytes[1] = 0x00;
00166 macBytes[2] = 0x5e;
00167 macBytes[3] = nextHopAddr.getDByte(1) & 0x7f;
00168 macBytes[4] = nextHopAddr.getDByte(2);
00169 macBytes[5] = nextHopAddr.getDByte(3);
00170 MACAddress multicastMacAddr;
00171 multicastMacAddr.setAddressBytes(bytes);
00172 sendPacketToNIC(msg, ie, multicastMacAddr);
00173 return;
00174 #endif
00175 }
00176
00177
00178 ARPCache::iterator it = arpCache.find(nextHopAddr);
00179
00180 if (it==arpCache.end())
00181 {
00182
00183 ARPCacheEntry *entry = new ARPCacheEntry();
00184 ARPCache::iterator where = arpCache.insert(arpCache.begin(), std::make_pair(nextHopAddr,entry));
00185 entry->myIter = where;
00186 entry->ie = ie;
00187
00188 EV << "Starting ARP resolution for " << nextHopAddr << "\n";
00189 initiateARPResolution(entry);
00190
00191
00192 entry->pendingPackets.push_back(msg);
00193 pendingQueue.insert(msg);
00194 }
00195 else if ((*it).second->pending)
00196 {
00197
00198 EV << "ARP resolution for " << nextHopAddr << " is pending, queueing up packet\n";
00199 (*it).second->pendingPackets.push_back(msg);
00200 pendingQueue.insert(msg);
00201 }
00202 else if ((*it).second->lastUpdate+cacheTimeout<simTime())
00203 {
00204 EV << "ARP cache entry for " << nextHopAddr << " expired, starting new ARP resolution\n";
00205
00206
00207 ARPCacheEntry *entry = (*it).second;
00208 entry->ie = ie;
00209 initiateARPResolution(entry);
00210
00211
00212 entry->pendingPackets.push_back(msg);
00213 pendingQueue.insert(msg);
00214 }
00215 else
00216 {
00217
00218 EV << "ARP cache hit, MAC address for " << nextHopAddr << " is " << (*it).second->macAddress << ", sending packet down\n";
00219 sendPacketToNIC(msg, ie, (*it).second->macAddress);
00220 }
00221 }
00222
00223 void ARP::initiateARPResolution(ARPCacheEntry *entry)
00224 {
00225 IPAddress nextHopAddr = entry->myIter->first;
00226 entry->pending = true;
00227 entry->numRetries = 0;
00228 entry->lastUpdate = 0;
00229 sendARPRequest(entry->ie, nextHopAddr);
00230
00231
00232 cMessage *msg = entry->timer = new cMessage("ARP timeout");
00233 msg->setContextPointer(entry);
00234 scheduleAt(simTime()+retryTimeout, msg);
00235
00236 numResolutions++;
00237 }
00238
00239 void ARP::sendPacketToNIC(cMessage *msg, InterfaceEntry *ie, const MACAddress& macAddress)
00240 {
00241
00242 Ieee802Ctrl *controlInfo = new Ieee802Ctrl();
00243 controlInfo->setDest(macAddress);
00244 msg->setControlInfo(controlInfo);
00245
00246
00247 send(msg, nicOutBaseGateId + ie->getNetworkLayerGateIndex());
00248 }
00249
00250 void ARP::sendARPRequest(InterfaceEntry *ie, IPAddress ipAddress)
00251 {
00252
00253 MACAddress myMACAddress = ie->getMacAddress();
00254 IPAddress myIPAddress = ie->ipv4Data()->getIPAddress();
00255
00256
00257 ASSERT(!myMACAddress.isUnspecified());
00258 ASSERT(!myIPAddress.isUnspecified());
00259
00260
00261 ARPPacket *arp = new ARPPacket("arpREQ");
00262 arp->setByteLength(ARP_HEADER_BYTES);
00263 arp->setOpcode(ARP_REQUEST);
00264 arp->setSrcMACAddress(myMACAddress);
00265 arp->setSrcIPAddress(myIPAddress);
00266 arp->setDestIPAddress(ipAddress);
00267
00268 static MACAddress broadcastAddress("ff:ff:ff:ff:ff:ff");
00269 sendPacketToNIC(arp, ie, broadcastAddress);
00270 numRequestsSent++;
00271 }
00272
00273 void ARP::requestTimedOut(cMessage *selfmsg)
00274 {
00275 ARPCacheEntry *entry = (ARPCacheEntry *)selfmsg->getContextPointer();
00276 entry->numRetries++;
00277 if (entry->numRetries < retryCount)
00278 {
00279
00280 IPAddress nextHopAddr = entry->myIter->first;
00281 EV << "ARP request for " << nextHopAddr << " timed out, resending\n";
00282 sendARPRequest(entry->ie, nextHopAddr);
00283 scheduleAt(simTime()+retryTimeout, selfmsg);
00284 return;
00285 }
00286
00287
00288
00289 MsgPtrVector& pendingPackets = entry->pendingPackets;
00290 EV << "ARP timeout, max retry count " << retryCount << " for "
00291 << entry->myIter->first << " reached. Dropping " << pendingPackets.size()
00292 << " waiting packets from the queue\n";
00293 while (!pendingPackets.empty())
00294 {
00295 MsgPtrVector::iterator i = pendingPackets.begin();
00296 cMessage *msg = (*i);
00297 pendingPackets.erase(i);
00298 pendingQueue.remove(msg);
00299 delete msg;
00300 }
00301 delete selfmsg;
00302 arpCache.erase(entry->myIter);
00303 delete entry;
00304 numFailedResolutions++;
00305 }
00306
00307
00308 bool ARP::addressRecognized(IPAddress destAddr, InterfaceEntry *ie)
00309 {
00310 if (rt->isLocalAddress(destAddr))
00311 return true;
00312
00313
00314
00315 if (!doProxyARP)
00316 return false;
00317 InterfaceEntry *rtie = rt->getInterfaceForDestAddr(destAddr);
00318 return rtie!=NULL && rtie!=ie;
00319 }
00320
00321 void ARP::dumpARPPacket(ARPPacket *arp)
00322 {
00323 EV << (arp->getOpcode()==ARP_REQUEST ? "ARP_REQ" : arp->getOpcode()==ARP_REPLY ? "ARP_REPLY" : "unknown type")
00324 << " src=" << arp->getSrcIPAddress() << " / " << arp->getSrcMACAddress()
00325 << " dest=" << arp->getDestIPAddress() << " / " << arp->getDestMACAddress() << "\n";
00326 }
00327
00328
00329 void ARP::processARPPacket(ARPPacket *arp)
00330 {
00331 EV << "ARP packet " << arp << " arrived:\n";
00332 dumpARPPacket(arp);
00333
00334
00335 IPRoutingDecision *controlInfo = check_and_cast<IPRoutingDecision*>(arp->removeControlInfo());
00336 InterfaceEntry *ie = ift->getInterfaceById(controlInfo->getInterfaceId());
00337 delete controlInfo;
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 MACAddress srcMACAddress = arp->getSrcMACAddress();
00368 IPAddress srcIPAddress = arp->getSrcIPAddress();
00369
00370 if (srcMACAddress.isUnspecified())
00371 error("wrong ARP packet: source MAC address is empty");
00372 if (srcIPAddress.isUnspecified())
00373 error("wrong ARP packet: source IP address is empty");
00374
00375 bool mergeFlag = false;
00376
00377 ARPCache::iterator it = arpCache.find(srcIPAddress);
00378 if (it!=arpCache.end())
00379 {
00380
00381 ARPCacheEntry *entry = (*it).second;
00382 updateARPCache(entry, srcMACAddress);
00383 mergeFlag = true;
00384 }
00385
00386
00387
00388 if (addressRecognized(arp->getDestIPAddress(), ie))
00389 {
00390
00391
00392 if (!mergeFlag)
00393 {
00394 ARPCacheEntry *entry;
00395 if (it!=arpCache.end())
00396 {
00397 entry = (*it).second;
00398 }
00399 else
00400 {
00401 entry = new ARPCacheEntry();
00402 ARPCache::iterator where = arpCache.insert(arpCache.begin(), std::make_pair(srcIPAddress,entry));
00403 entry->myIter = where;
00404 entry->ie = ie;
00405
00406 entry->pending = false;
00407 entry->timer = NULL;
00408 entry->numRetries = 0;
00409 }
00410 updateARPCache(entry, srcMACAddress);
00411 }
00412
00413
00414 switch (arp->getOpcode())
00415 {
00416 case ARP_REQUEST:
00417 {
00418 EV << "Packet was ARP REQUEST, sending REPLY\n";
00419
00420
00421 MACAddress myMACAddress = ie->getMacAddress();
00422 IPAddress myIPAddress = ie->ipv4Data()->getIPAddress();
00423
00424
00425 arp->setName("arpREPLY");
00426 IPAddress origDestAddress = arp->getDestIPAddress();
00427 arp->setDestIPAddress(srcIPAddress);
00428 arp->setDestMACAddress(srcMACAddress);
00429 arp->setSrcIPAddress(origDestAddress);
00430 arp->setSrcMACAddress(myMACAddress);
00431 arp->setOpcode(ARP_REPLY);
00432 delete arp->removeControlInfo();
00433 sendPacketToNIC(arp, ie, srcMACAddress);
00434 numRepliesSent++;
00435 break;
00436 }
00437 case ARP_REPLY:
00438 {
00439 EV << "Discarding packet\n";
00440 delete arp;
00441 break;
00442 }
00443 case ARP_RARP_REQUEST: error("RARP request received: RARP is not supported");
00444 case ARP_RARP_REPLY: error("RARP reply received: RARP is not supported");
00445 default: error("Unsupported opcode %d in received ARP packet",arp->getOpcode());
00446 }
00447 }
00448 else
00449 {
00450
00451 EV << "IP address " << arp->getDestIPAddress() << " not recognized, dropping ARP packet\n";
00452 delete arp;
00453 }
00454 }
00455
00456 void ARP::updateARPCache(ARPCacheEntry *entry, const MACAddress& macAddress)
00457 {
00458 EV << "Updating ARP cache entry: " << entry->myIter->first << " <--> " << macAddress << "\n";
00459
00460
00461 if (entry->pending)
00462 {
00463 entry->pending = false;
00464 delete cancelEvent(entry->timer);
00465 entry->timer = NULL;
00466 entry->numRetries = 0;
00467 }
00468 entry->macAddress = macAddress;
00469 entry->lastUpdate = simTime();
00470
00471
00472 MsgPtrVector& pendingPackets = entry->pendingPackets;
00473 while (!pendingPackets.empty())
00474 {
00475 MsgPtrVector::iterator i = pendingPackets.begin();
00476 cMessage *msg = (*i);
00477 pendingPackets.erase(i);
00478 pendingQueue.remove(msg);
00479 EV << "Sending out queued packet " << msg << "\n";
00480 sendPacketToNIC(msg, entry->ie, macAddress);
00481 }
00482 }
00483
00484