#include <ARP.h>
|
|
|
|
|
00086 {}
|
|
00075 { 00076 while (!arpCache.empty()) 00077 { 00078 ARPCache::iterator i = arpCache.begin(); 00079 delete (*i).second; 00080 arpCache.erase(i); 00081 } 00082 }
|
|
00307 { 00308 if (rt->localDeliver(destAddr)) 00309 return true; 00310 00311 // respond to Proxy ARP request: if we can route this packet (and the 00312 // output port is different from this one), say yes 00313 if (!doProxyARP) 00314 return false; 00315 InterfaceEntry *rtie = rt->interfaceForDestAddr(destAddr); 00316 return rtie!=NULL && rtie!=ie; 00317 }
|
|
00320 { 00321 EV << (arp->getOpcode()==ARP_REQUEST ? "ARP_REQ" : arp->getOpcode()==ARP_REPLY ? "ARP_REPLY" : "unknown type") 00322 << " src=" << arp->getSrcIPAddress() << " / " << arp->getSrcMACAddress() 00323 << " dest=" << arp->getDestIPAddress() << " / " << arp->getDestMACAddress() << "\n"; 00324 }
|
|
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 }
|
|
00328 { 00329 EV << "ARP packet " << arp << " arrived:\n"; 00330 dumpARPPacket(arp); 00331 00332 // extract input port 00333 IPRoutingDecision *controlInfo = check_and_cast<IPRoutingDecision*>(arp->removeControlInfo()); 00334 InterfaceEntry *ie = ift->interfaceAt(controlInfo->interfaceId()); 00335 delete controlInfo; 00336 00337 // 00338 // Recipe a'la RFC 826: 00339 // 00340 // ?Do I have the hardware type in ar$hrd? 00341 // Yes: (almost definitely) 00342 // [optionally check the hardware length ar$hln] 00343 // ?Do I speak the protocol in ar$pro? 00344 // Yes: 00345 // [optionally check the protocol length ar$pln] 00346 // Merge_flag := false 00347 // If the pair <protocol type, sender protocol address> is 00348 // already in my translation table, update the sender 00349 // hardware address field of the entry with the new 00350 // information in the packet and set Merge_flag to true. 00351 // ?Am I the target protocol address? 00352 // Yes: 00353 // If Merge_flag is false, add the triplet <protocol type, 00354 // sender protocol address, sender hardware address> to 00355 // the translation table. 00356 // ?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!) 00357 // Yes: 00358 // Swap hardware and protocol fields, putting the local 00359 // hardware and protocol addresses in the sender fields. 00360 // Set the ar$op field to ares_op$REPLY 00361 // Send the packet to the (new) target hardware address on 00362 // the same hardware on which the request was received. 00363 // 00364 00365 MACAddress srcMACAddress = arp->getSrcMACAddress(); 00366 IPAddress srcIPAddress = arp->getSrcIPAddress(); 00367 00368 if (srcMACAddress.isUnspecified()) 00369 error("wrong ARP packet: source MAC address is empty"); 00370 if (srcIPAddress.isUnspecified()) 00371 error("wrong ARP packet: source IP address is empty"); 00372 00373 bool mergeFlag = false; 00374 // "If ... sender protocol address is already in my translation table" 00375 ARPCache::iterator it = arpCache.find(srcIPAddress); 00376 if (it!=arpCache.end()) 00377 { 00378 // "update the sender hardware address field" 00379 ARPCacheEntry *entry = (*it).second; 00380 updateARPCache(entry, srcMACAddress); 00381 mergeFlag = true; 00382 } 00383 00384 // "?Am I the target protocol address?" 00385 // if Proxy ARP is enabled, we also have to reply if we're a router to the dest IP address 00386 if (addressRecognized(arp->getDestIPAddress(), ie)) 00387 { 00388 // "If Merge_flag is false, add the triplet protocol type, sender 00389 // protocol address, sender hardware address to the translation table" 00390 if (!mergeFlag) 00391 { 00392 ARPCacheEntry *entry; 00393 if (it!=arpCache.end()) 00394 { 00395 entry = (*it).second; 00396 } 00397 else 00398 { 00399 entry = new ARPCacheEntry(); 00400 ARPCache::iterator where = arpCache.insert(arpCache.begin(), std::make_pair(srcIPAddress,entry)); 00401 entry->myIter = where; 00402 entry->ie = ie; 00403 00404 entry->pending = false; 00405 entry->timer = NULL; 00406 entry->numRetries = 0; 00407 } 00408 updateARPCache(entry, srcMACAddress); 00409 } 00410 00411 // "?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!)" 00412 switch (arp->getOpcode()) 00413 { 00414 case ARP_REQUEST: 00415 { 00416 EV << "Packet was ARP REQUEST, sending REPLY\n"; 00417 00418 // find our own IP address and MAC address on the given interface 00419 MACAddress myMACAddress = ie->macAddress(); 00420 IPAddress myIPAddress = ie->ipv4()->inetAddress(); 00421 00422 // "Swap hardware and protocol fields", etc. 00423 arp->setName("arpREPLY"); 00424 IPAddress origDestAddress = arp->getDestIPAddress(); 00425 arp->setDestIPAddress(srcIPAddress); 00426 arp->setDestMACAddress(srcMACAddress); 00427 arp->setSrcIPAddress(origDestAddress); 00428 arp->setSrcMACAddress(myMACAddress); 00429 arp->setOpcode(ARP_REPLY); 00430 delete arp->removeControlInfo(); 00431 sendPacketToNIC(arp, ie, srcMACAddress); 00432 numRepliesSent++; 00433 break; 00434 } 00435 case ARP_REPLY: 00436 { 00437 EV << "Discarding packet\n"; 00438 delete arp; 00439 break; 00440 } 00441 case ARP_RARP_REQUEST: error("RARP request received: RARP is not supported"); 00442 case ARP_RARP_REPLY: error("RARP reply received: RARP is not supported"); 00443 default: error("Unsupported opcode %d in received ARP packet",arp->getOpcode()); 00444 } 00445 } 00446 else 00447 { 00448 // address not recognized 00449 EV << "IP address " << arp->getDestIPAddress() << " not recognized, dropping ARP packet\n"; 00450 delete arp; 00451 } 00452 }
|
|
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 }
|
|
00272 { 00273 ARPCacheEntry *entry = (ARPCacheEntry *)selfmsg->contextPointer(); 00274 entry->numRetries++; 00275 if (entry->numRetries < retryCount) 00276 { 00277 // retry 00278 IPAddress nextHopAddr = entry->myIter->first; 00279 EV << "ARP request for " << nextHopAddr << " timed out, resending\n"; 00280 sendARPRequest(entry->ie, nextHopAddr); 00281 scheduleAt(simTime()+retryTimeout, selfmsg); 00282 return; 00283 } 00284 00285 // max retry count reached: ARP failure. 00286 // throw out entry from cache, delete pending messages 00287 MsgPtrVector& pendingPackets = entry->pendingPackets; 00288 EV << "ARP timeout, max retry count " << retryCount << " for " 00289 << entry->myIter->first << " reached. Dropping " << pendingPackets.size() 00290 << " waiting packets from the queue\n"; 00291 while (!pendingPackets.empty()) 00292 { 00293 MsgPtrVector::iterator i = pendingPackets.begin(); 00294 cMessage *msg = (*i); 00295 pendingPackets.erase(i); 00296 pendingQueue.remove(msg); 00297 delete msg; 00298 } 00299 delete selfmsg; 00300 arpCache.erase(entry->myIter); 00301 delete entry; 00302 numFailedResolutions++; 00303 }
|
|
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 // both must be set 00255 ASSERT(!myMACAddress.isUnspecified()); 00256 ASSERT(!myIPAddress.isUnspecified()); 00257 00258 // fill out everything in ARP Request packet except dest MAC address 00259 ARPPacket *arp = new ARPPacket("arpREQ"); 00260 arp->setByteLength(ARP_HEADER_BYTES); 00261 arp->setOpcode(ARP_REQUEST); 00262 arp->setSrcMACAddress(myMACAddress); 00263 arp->setSrcIPAddress(myIPAddress); 00264 arp->setDestIPAddress(ipAddress); 00265 00266 static MACAddress broadcastAddress("ff:ff:ff:ff:ff:ff"); 00267 sendPacketToNIC(arp, ie, broadcastAddress); 00268 numRequestsSent++; 00269 }
|
|
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 }
|
|
00455 { 00456 EV << "Updating ARP cache entry: " << entry->myIter->first << " <--> " << macAddress << "\n"; 00457 00458 // update entry 00459 if (entry->pending) 00460 { 00461 entry->pending = false; 00462 delete cancelEvent(entry->timer); 00463 entry->timer = NULL; 00464 entry->numRetries = 0; 00465 } 00466 entry->macAddress = macAddress; 00467 entry->lastUpdate = simTime(); 00468 00469 // process queued packets 00470 MsgPtrVector& pendingPackets = entry->pendingPackets; 00471 while (!pendingPackets.empty()) 00472 { 00473 MsgPtrVector::iterator i = pendingPackets.begin(); 00474 cMessage *msg = (*i); 00475 pendingPackets.erase(i); 00476 pendingQueue.remove(msg); 00477 EV << "Sending out queued packet " << msg << "\n"; 00478 sendPacketToNIC(msg, entry->ie, macAddress); 00479 } 00480 }
|
|
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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|