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