|
INET Framework for OMNeT++/OMNEST
|
00001 00020 #include "RIPRouting.h" 00021 #include "IPRoute.h" 00022 #include <vector> 00023 00024 #ifndef WITHOUT_IPv4 00025 #include "IPv4InterfaceData.h" 00026 #endif 00027 00028 #define BROADCAST "255.255.255.255" 00030 using namespace std; 00031 00032 Define_Module(RIPRouting); 00033 00035 std::ostream& operator<<(std::ostream& os, const RIPinterface& e) 00036 { 00037 os << "ID = " << e.intID << "; addr = " << e.addr << "; mask = " << e.mask << "; pass = " << e.passive << "; broad = " << e.broadcast; 00038 return os; 00039 }; 00040 00042 std::ostream& operator<<(std::ostream& os, const RIPRouteTimer& e) 00043 { 00044 if (e.timer == NULL) 00045 os << "Adresa= " << e.route->getHost() << "; NIC "; 00046 else 00047 os << "Adresa= " << e.route->getHost() << "; " << e.timer->getFullName() << " ArrivalTime: " << e.timer->getArrivalTime(); 00048 return os; 00049 }; 00050 00052 std::ostream& operator<<(std::ostream& os, const RIPRedistribution& e) 00053 { 00054 if (e.redistrinute) 00055 os << "Redistribuce: YES; Protokol: " << e.protocol << "; Metrika: " << e.metric; 00056 else 00057 os << "Redistribuce: NO; Protokol: " << e.protocol << "; Metrika: " << e.metric; 00058 return os; 00059 }; 00060 00062 RIPRouting::~RIPRouting() 00063 { 00064 for (int i = 0; i < (int) routeTimer.size(); i++) 00065 { 00066 if (routeTimer[i].timer != NULL) 00067 { 00068 if (routeTimer[i].timer->isScheduled()) 00069 cancelEvent(routeTimer[i].timer); 00070 delete routeTimer[i].timer; 00071 } 00072 } 00073 if (triggerTimer != NULL) 00074 { 00075 if (triggerTimer->isScheduled()) 00076 cancelEvent(triggerTimer); 00077 delete triggerTimer; 00078 } 00079 } 00080 00088 IPAddress getMask(IPAddress addr) 00089 { 00090 IPAddress mask; 00091 if (addr< "126.255.255.255") 00092 mask = "255.0.0.0"; // A 00093 else if (addr < "191.255.255.255") 00094 mask = "255.255.0.0"; // B 00095 else 00096 mask = "255.255.255.0"; // C 00097 return mask; 00098 } 00099 00106 void RIPRouting::insertIft(InterfaceEntry * entryIFT) 00107 { 00108 RIPinterface newIftEntry; 00109 00110 newIftEntry.intID = entryIFT->getInterfaceId(); 00111 00112 if (entryIFT->isBroadcast()) 00113 newIftEntry.broadcast = true; 00114 else 00115 newIftEntry.broadcast = false; 00116 00117 if (entryIFT->isLoopback()) 00118 newIftEntry.loopback = true; 00119 else 00120 newIftEntry.loopback = false; 00121 00122 IPv4InterfaceData *ipv4 = entryIFT->ipv4Data(); 00123 IPAddress IPaddr = ipv4->getIPAddress(); 00124 newIftEntry.addr = IPvXAddress(IPaddr); 00125 newIftEntry.mask = ipv4->getNetmask(); 00126 newIftEntry.passive = false; 00127 newIftEntry.entry = entryIFT; 00128 ripIft.push_back(newIftEntry); 00129 } 00130 00137 void RIPRouting::sendTrigger() 00138 { 00139 if (triggerTimer != NULL) 00140 { 00141 if (triggerTimer->isScheduled()) 00142 cancelEvent(triggerTimer); 00143 delete triggerTimer; 00144 } 00145 // vysli trigger zpravu 00146 RIPTimer* newTimer = new RIPTimer("Trigger"); 00147 newTimer->setTimerKind(trigger); 00148 triggerTimer = newTimer; 00149 scheduleAt(simTime() + exponential(3), newTimer); 00150 } 00151 00161 int RIPRouting::getRouteRT (RIPTimer *timer) 00162 { 00163 for (int i = 0; i < (int)routeTimer.size(); i++) 00164 { 00165 if (routeTimer[i].timer == timer) 00166 { 00167 return i; 00168 } 00169 } 00170 return -1; 00171 } 00172 00182 int RIPRouting::getTimerRT (IPRoute *route) 00183 { 00184 for(int i = 0; i < (int) routeTimer.size(); i++) 00185 { 00186 if (routeTimer[i].route == route) 00187 { 00188 return i; 00189 } 00190 } 00191 return -1; 00192 } 00193 00203 RIPTimer * RIPRouting::updateTimer(int type, RIPRouteTimer * entry) 00204 { 00205 RIPTimer *timer = new RIPTimer(); 00206 timer->setTimerKind(type); 00207 00208 switch(type) 00209 { 00210 case hello: 00211 timer->setName("Hello"); 00212 scheduleAt(simTime() + 30.0 + exponential(1), timer); 00213 break; 00214 00215 case timeout: 00216 timer->setName("Timeout"); 00217 scheduleAt(simTime() + 120.0, timer); 00218 if (entry != NULL && entry->timer != NULL) 00219 { 00220 cancelEvent(entry->timer); 00221 delete entry->timer; 00222 entry->timer = timer; 00223 } 00224 break; 00225 00226 case garbage: 00227 timer->setName("Garbage"); 00228 scheduleAt(simTime() + 180.0, timer); 00229 entry->timer = timer; 00230 break; 00231 } 00232 return timer; 00233 } 00234 00243 bool RIPRouting::checkTwin(IPRoute * entryRT) 00244 { 00245 bool cont = false; 00246 for (int k = 0; k < (int) routeTwins.size(); k++) 00247 { 00248 if (entryRT == routeTwins[k].route1 || entryRT == routeTwins[k].route2) 00249 { 00250 EV << hostname << ": Takováto dvojice jiz existuje!!!" << endl; 00251 cont = true; 00252 } 00253 } 00254 return cont; 00255 } 00256 00264 void RIPRouting::sendPacket(int command, IPAddress destAddr) 00265 { 00266 EV << "RIPRouting::sendPacket" << endl; 00267 IPvXAddress destXAddr = IPvXAddress(destAddr); 00268 bool right = false; 00269 RIPPacket *msg; 00270 00271 // posilani broadcast zprav na vsechny vystupni interfacy 00272 if (destAddr == BROADCAST) 00273 { 00274 EV << "Broadcast" << endl; 00275 for (int i = 0; i < (int)ripIft.size(); i++) 00276 { 00277 // kontrola interface, nezasilame na pasivni interfaci, jen na broadcastove 00278 // if (ripIft[i].passive || !ripIft[i].broadcast) 00279 if (ripIft[i].passive || ripIft[i].loopback) 00280 { 00281 if (ripIft[i].passive) 00282 EV << "FUJ" << endl; 00283 else if (ripIft[i].loopback) 00284 EV << "FUJ2" << endl; 00285 continue;} 00286 00287 // posilame jen do siti, ktere jsou definovane v network 00288 for (int j = 0; j < (int) network.size(); j++) 00289 { 00290 EV << hostname << ": Kontrola na IP interfacu " << ripIft[i].addr.get4() << "s IP adresou v network: " << network[j] << " s maskou: " << getMask(network[j]) << endl; 00291 if (IPAddress::maskedAddrAreEqual(network[j], ripIft[i].addr.get4(), getMask(network[j]))) 00292 { 00293 right = true; 00294 break; 00295 } 00296 else 00297 right = false; 00298 } 00299 // adresa neni v network 00300 if (right == false) 00301 { EV << "FUJ2" << endl; 00302 continue;} 00303 00304 // vytvori novou RIP zpravu 00305 if ((msg = createPacket(command, ripIft[i].entry)) == NULL) 00306 return; 00307 00308 // UDP kontrolni informace (porty, IP adresy, interface) 00309 UDPControlInfo *ctrl = new UDPControlInfo(); 00310 ctrl->setSrcPort(localPort); 00311 ctrl->setDestAddr(destXAddr); 00312 ctrl->setDestPort(destPort); 00313 ctrl->setSrcAddr(ripIft[i].addr); 00314 ctrl->setInterfaceId(ripIft[i].intID); 00315 msg->setControlInfo(ctrl); 00316 send(msg, "udpOut"); 00317 EV << hostname << ": Posilam zpravu Broadcastem se zdrojem: "<< ripIft[i].addr << endl; 00318 } 00319 } 00320 // posilani aktualizace na konkretni IP adresu (odpoved na Request) 00321 else 00322 { 00323 EV << hostname << ": Posilam zpravu na adresu:" << destAddr << endl; 00324 IPRoute * route = (IPRoute *) rt->findBestMatchingRoute(destAddr); 00325 00326 // vytvori novou RIP zpravu 00327 if ((msg = createPacket(command, route->getInterface())) == NULL) 00328 return; 00329 00330 // UDP kontrolni informace (porty, IP adresy, interface) 00331 UDPControlInfo *ctrl = new UDPControlInfo(); 00332 ctrl->setSrcPort(localPort); 00333 ctrl->setDestAddr(destXAddr); 00334 ctrl->setDestPort(destPort); 00335 ctrl->setInterfaceId(route->getInterface()->getInterfaceId()); 00336 msg->setControlInfo(ctrl); 00337 send(msg, "udpOut"); 00338 } 00339 } 00340 00349 RIPPacket* RIPRouting::createPacket(int command, InterfaceEntry * entry) 00350 { 00351 RIPPacket *msg = new RIPPacket(); // novy paket 00352 vector<RouteEntry> newEntry; // vektor cest 00353 int size; // mnozstvi cest 00354 00355 // Request zprava 00356 if (command == Request) 00357 { 00358 msg->setName("RIPRequest"); 00359 RouteEntry entry; 00360 entry.addressID = 0; 00361 entry.metric = 16; 00362 newEntry.push_back(entry); 00363 } 00364 // Response zprava 00365 else 00366 { 00367 msg->setName("RIPResponse"); 00368 newEntry = fillNetworks(entry); 00369 } 00370 00371 // kontrola, zda mame co posilat 00372 if (newEntry.size() <= 0) 00373 return NULL; 00374 00375 msg->setCommand(command); 00376 msg->setKind(UDP_C_DATA); 00377 size = newEntry.size(); 00378 msg->setRouteEntryArraySize(size); 00379 00380 // naplneni zpravy cestami 00381 for(int i = 0; i < size; i++) 00382 msg->setRouteEntry(i, newEntry[i]); 00383 00384 return msg; 00385 } 00386 00399 vector<RouteEntry> RIPRouting::fillNetworks(InterfaceEntry * IntEntry) 00400 { 00401 IPRoute *entryRT = new IPRoute(); // routovaci tabulka 00402 RouteEntry entry; // nova polozka s adresou 00403 vector<RouteEntry> newEntry; // vektor zasilanych adres 00404 IPAddress mask; // sitova maska 00405 int sizeTab = rt->getNumRoutes(); // velikost routovaci tabulky 00406 int sizeNet = network.size(); // pocet siti, ktere se maji posilat 00407 00408 00409 // ber postupne site z routovaci tabulky 00410 for (int i = 0; i < sizeTab; i++) 00411 { 00412 // pokud cesta ma jako zdroj RIP (prisla od souseda), pridej ji... 00413 entryRT = const_cast<IPRoute*>(rt->getRoute(i)); 00414 if (entryRT->getSource() == INET_API IPRoute::RIP) 00415 { 00416 // split horizon => neposilame cesty, ktere jsme pres toto roshrani dostali 00417 if (entryRT->getInterface() == IntEntry) 00418 continue; 00419 00420 // kontrola na dve stejne cesty 00421 bool cont = false; 00422 for (int j = 0; j < (int) routeTwins.size(); j++) 00423 { 00424 if (entryRT == routeTwins[j].route1 || entryRT == routeTwins[j].route2) 00425 { 00426 if (IntEntry == routeTwins[j].route1->getInterface() || IntEntry == routeTwins[j].route2->getInterface()) 00427 { 00428 EV << hostname << ": FillNetworks: Jedna se o dvojce, nikam ji nedavej!!!" << endl; 00429 cont = true; 00430 } 00431 } 00432 } 00433 if (cont == true) 00434 continue; 00435 00436 // pridava RIP cestu 00437 EV << hostname << ": Posilam podle RIP zaznamu IP: " << entry.ipAddress << endl; 00438 entry.addressID = 2; 00439 entry.mustBeZero2 = 0; 00440 entry.mustBeZero3 = 0; 00441 entry.mustBeZero4 = 0; 00442 entry.ipAddress = entryRT->getHost(); 00443 entry.metric = entryRT->getMetric(); 00444 newEntry.push_back(entry); 00445 continue; 00446 } // ... konec cest se zdrojem RIP 00447 00448 //... a prihod lokalni adresy, ktere jsou nastavene v konfiguraku (network) 00449 // ber postupne site nastavene v network a porovnavej ji s cestou z routovaci tabulky 00450 if (entryRT->getSource() == INET_API IPRoute::IFACENETMASK) 00451 { 00452 for (int j = 0; j < sizeNet; j++) 00453 { 00454 if (IPAddress::maskedAddrAreEqual(network[j], entryRT->getHost(), getMask(network[j]))) 00455 { 00456 EV << hostname << ": Posilam IP: " << entry.ipAddress << endl; 00457 entry.addressID = 2; 00458 entry.mustBeZero2 = 0; 00459 entry.mustBeZero3 = 0; 00460 entry.mustBeZero4 = 0; 00461 entry.ipAddress = entryRT->getHost(); 00462 entry.metric = entryRT->getMetric(); 00463 newEntry.push_back(entry); 00464 } 00465 } 00466 } // ...konec lokalnich adres 00467 } // for 00468 00469 00470 // ziskej redistribuvane site 00471 vector<RouteEntry> redistrEntry; 00472 bool red; 00473 if (redistr.redistrinute) 00474 { 00475 EV << hostname << ": Redistribuce zapnuta" << endl; 00476 // ziskani cest z OSPF 00477 redistrEntry = getOSPFRoutes(); 00478 00479 // OSPF dava do routovaci tabulky i primo pripojene site 00480 // ty je nutne vyeliminovat 00481 for(int j = 0; j < (int) redistrEntry.size(); j++) 00482 { 00483 red = true; 00484 for (int i = 0; i < (int) ripIft.size(); i++) 00485 { 00486 if (IPAddress::maskedAddrAreEqual(ripIft[i].addr.get4(), redistrEntry[j].ipAddress, ripIft[i].mask.get4())) 00487 red = false; 00488 } 00489 if (red) 00490 newEntry.push_back(redistrEntry[j]); 00491 } 00492 }// ...if redistribuce 00493 00494 return newEntry; 00495 } 00496 00497 00507 void RIPRouting::processRequest(RIPPacket *msg) 00508 { 00509 EV << "RIPRouting::processRequest" << endl; 00510 RouteEntry entryReq = msg->getRouteEntry(0); // 1. zaznam z prichozi zpravy 00511 00512 if ((msg->getRouteEntryArraySize() == 1) && (entryReq.addressID == 0) && (entryReq.metric == 16)) 00513 { 00514 // ...posli aktualizacni zaznam se vsemi cestami 00515 this->sendPacket(Response, udpCtrl->getSrcAddr().get4()); 00516 } 00517 else 00518 { 00519 // ... jinak posli jen pozadovane zaznamy 00520 // mozno udelat pri nejakem rozsireni, ale pri simulaci 00521 // prakticky nepouzitelne; pouziva se k siagnostickym ucelum 00522 } 00523 } 00524 00533 void RIPRouting::processResponse(RIPPacket *msg) 00534 { 00535 // zkontroluj src port 520 (RIP), jinak ignoruj 00536 if ((udpCtrl->getSrcPort()) != destPort) 00537 return; 00538 00539 int max = msg->getRouteEntryArraySize(); // pocet prijatych cest 00540 IPRoute *entryRT = new IPRoute(); // zaznam z routovaci tabulky 00541 int newMetric; // metrika ze zpravy 00542 int oldMetric; // metrika z routovaci tabulky 00543 bool change = false; // hlida zmeny, true = trigged zprava 00544 00545 // prochazej vsechny prijate zaznamy 00546 for (int i = 0; i < max; i++) 00547 { 00548 // pokud nejde o IP adresu, preskoc zaznam 00549 if (msg->getRouteEntry(i).addressID != 2) 00550 continue; 00551 00552 // pokud je metrika vetsi nez infinite, preskoc zaznam 00553 if (msg->getRouteEntry(i).metric >= 16) 00554 continue; 00555 00556 // loopbacky taky ignoruj 00557 if (IPAddress::maskedAddrAreEqual(msg->getRouteEntry(i).ipAddress, "127.0.0.0", "255.0.0.0")) 00558 continue; 00559 00560 // adresy tridy D a E ignoruj taktez 00561 if (!(msg->getRouteEntry(i).ipAddress < "223.255.255.255")) 00562 continue; 00563 00564 // najdi IP adresu v routovaci tabulce 00565 EV << hostname << ": Adresa " << i << ": "<< msg->getRouteEntry(i).ipAddress << endl; 00566 entryRT = const_cast<IPRoute*>(rt->findBestMatchingRoute(msg->getRouteEntry(i).ipAddress)); 00567 00568 // pro exitující twin 00569 if (checkTwin(entryRT)) 00570 { 00571 EV << hostname << "Existuje dvojice, hledam routu" << endl; 00572 for (int k = 0; k < (int) routeTwins.size(); k++) 00573 { 00574 if (entryRT == routeTwins[k].route1 || entryRT == routeTwins[k].route2) 00575 { 00576 EV << hostname << "Routa nalezena: " << endl; 00577 if (udpCtrl->getSrcAddr().get4() == routeTwins[k].route1->getGateway()) 00578 { 00579 entryRT = routeTwins[k].route1; 00580 EV << entryRT->info() << endl; 00581 } 00582 else if (udpCtrl->getSrcAddr().get4() == routeTwins[k].route2->getGateway()) 00583 { 00584 entryRT = routeTwins[k].route2; 00585 EV << entryRT->info() << endl; 00586 } 00587 break; 00588 } 00589 } 00590 } //if twin 00591 00592 // pokud adresa neni v routovaci tabulce, je treba pridat novy zaznam 00593 if (entryRT == NULL || ((entryRT->getGateway() != udpCtrl->getSrcAddr().get4()) && (msg->getRouteEntry(i).metric + 1 == entryRT->getMetric()) && !checkTwin(entryRT))) 00594 { 00595 IPRoute *entry = new IPRoute(); // nova cesta 00596 RIPRouteTwins twin; // dvojice stejnych cest 00597 int id; 00598 00599 // zjisti z jakeho interfacu zprava prisla 00600 // kvuli urceni masky a adresy cesty 00601 for (int j = 0; j < (int) ripIft.size(); j++) 00602 if (ripIft[j].intID == udpCtrl->getInterfaceId()) 00603 { 00604 id = j; 00605 break; 00606 } 00607 00608 // pokud je adresa ze stejne tridy dostane masku podle masky na interfacu 00609 if (IPAddress::maskedAddrAreEqual(msg->getRouteEntry(i).ipAddress, ripIft[id].addr.get4(), getMask(msg->getRouteEntry(i).ipAddress))) 00610 entry->setNetmask(ripIft[id].mask.get4()); 00611 else 00612 entry->setNetmask(getMask(msg->getRouteEntry(i).ipAddress)); 00613 00614 // vyplni vsechny potrebne informace a vlozi cestu do tabulky 00615 entry->setHost(msg->getRouteEntry(i).ipAddress); 00616 entry->setGateway(udpCtrl->getSrcAddr().get4()); 00617 entry->setInterface(ift->getInterfaceById(udpCtrl->getInterfaceId())); 00618 entry->setType(INET_API IPRoute::REMOTE); 00619 entry->setSource(INET_API IPRoute::RIP); 00620 entry->setMetric(msg->getRouteEntry(i).metric + 1); 00621 rt->addRoute(entry); 00622 EV << "Pridavam adresu: "<< msg->getRouteEntry(i).ipAddress << endl; 00623 00624 // jde o druhy zaznam stejne cesty 00625 if (entryRT != NULL) 00626 { 00627 EV << hostname << ": Pridavam dvojcata: " << endl; 00628 twin.route1 = entryRT; 00629 twin.route2 = entry; 00630 EV << twin.route1->info() << endl; 00631 EV << twin.route2->info() << endl; 00632 routeTwins.push_back(twin); 00633 } 00634 // zaznam do RouteEntry + nastavi timer timeout 00635 RIPRouteTimer newEntry; 00636 newEntry.route = entry; 00637 newEntry.timer = updateTimer(timeout, NULL); 00638 routeTimer.push_back(newEntry); 00639 } 00640 // adresa jiz v routovaci tabulce je a nejedna se o druhou cestu do stejného místa 00641 else 00642 { 00643 EV << hostname << ": K teto adrese sedi adresa: " << entryRT->getHost() << endl; 00644 newMetric = msg->getRouteEntry(i).metric; 00645 oldMetric = entryRT->getMetric(); 00646 int j = getTimerRT(entryRT); 00647 00648 // updatuj timery 00649 if (entryRT->getGateway() == udpCtrl->getSrcAddr().get4()) 00650 updateTimer(timeout, &routeTimer[j]); 00651 00652 // pokud je nova metrika mensi nez metrika v tabulce, 00653 // prepis ji a zapis novou adresu gateway (next hop) 00654 if (((newMetric + 1) < oldMetric)) 00655 { 00656 EV << "Stara metrika: " << oldMetric << ". Nova metrika: " << newMetric << endl; 00657 entryRT->setMetric(newMetric + 1); 00658 entryRT->setGateway(udpCtrl->getSrcAddr().get4()); 00659 00660 // nastavi upravene ceste spravny odkaz na interface 00661 for (int k = 0; k < (int) ripIft.size(); k++) 00662 { 00663 if (udpCtrl->getInterfaceId() == ripIft[k].intID) 00664 { 00665 entryRT->setInterface(ripIft[k].entry); 00666 break; 00667 } 00668 } 00669 // vysle updaty 00670 change = true; 00671 } 00672 } // else 00673 } // for 00674 00675 // vysle updat 00676 if (change == true) 00677 sendTrigger(); 00678 } 00679 00691 void RIPRouting::processPacket(cMessage *msg) 00692 { 00693 int max; // pocet cest v prichozi zprave 00694 cPacket *packet = dynamic_cast<cPacket *> (msg); // pretipujeme na cPacket 00695 udpCtrl = new UDPControlInfo(); // naalokujeme misto pro UDP kontrolni info 00696 udpCtrl = dynamic_cast<UDPControlInfo *>(packet->getControlInfo()); 00697 IPvXAddress srcIP = udpCtrl->getSrcAddr(); // IP adresa zdroje 00698 RIPPacket *hMsg = dynamic_cast<RIPPacket *> (msg); // pretipujeme na RIP zpravu 00699 IPRoute * route = new IPRoute(); // naalokujeme cestu z RT 00700 EV << hostname << ": IP adresa zdroje RIP zpravy je:" << srcIP << endl; 00701 00702 // zkontroluj IP adresu zdroje 00703 // sit zdroje neni v routovaci tabulce nebo neni primo pripojena 00704 if ((route = const_cast<IPRoute*> (rt->findBestMatchingRoute(srcIP.get4()))) == NULL) 00705 { 00706 error("Nejspise se jedna o podvrzenou zpravu, chybna zdrojova IP adresa1"); 00707 return; 00708 } 00709 else if (route->getType() != INET_API IPRoute::DIRECT) 00710 { 00711 error("Nejspise se jedna o podvrzenou zpravu, chybna zdrojova IP adresa2"); 00712 return; 00713 } 00714 00715 // zkontroluj verzi a prislusna policka na spravnost 00716 switch(hMsg->getVersion()) 00717 { 00718 case 0: 00719 return; 00720 case 1: 00721 if (!(hMsg->getMustBeZero1() == 0)) 00722 return; 00723 max = hMsg->getRouteEntryArraySize(); 00724 00725 for (int i = 0; i < max; i++) 00726 { 00727 if (!(hMsg->getRouteEntry(i).mustBeZero2 == 0)) 00728 return; 00729 if (!(hMsg->getRouteEntry(i).mustBeZero3 == 0)) 00730 return; 00731 if (!(hMsg->getRouteEntry(i).mustBeZero4 == 0)) 00732 return; 00733 } 00734 break; 00735 default: 00736 break; 00737 } 00738 00739 // dale zpracovavej podle toho, zda se jedna o Request nebo Response 00740 if (hMsg->getCommand() == Request) 00741 this->processRequest(hMsg); 00742 else if (hMsg->getCommand() == Response) 00743 this->processResponse(hMsg); 00744 delete msg; 00745 } 00746 00756 void RIPRouting::initialize (int stage) 00757 { 00758 // v stage 2 se registruji interfacy 00759 if (stage == 3) 00760 { 00761 // nastaveni portu a spojeni s portem 00762 localPort = par("localPort"); 00763 destPort = par("destPort"); 00764 bindToPort(localPort); 00765 00766 // routovaci tabulka, tabulka interfacu 00767 // notifikacni tabulka a odebirani upozorneni 00768 rt = RoutingTableAccess().get(); 00769 ift = InterfaceTableAccess().get(); 00770 nb = NotificationBoardAccess().get(); 00771 nb->subscribe(this, NF_INTERFACE_STATE_CHANGED); 00772 00773 // dalsi inicializace 00774 triggerTimer = NULL; 00775 redistr.redistrinute = false; 00776 redistr.metric = 0; 00777 00778 // vlastni tabulka interfacu s info, ktere potrebuji 00779 InterfaceEntry *entryIFT = new InterfaceEntry(); 00780 for (int i = 0; i < ift->getNumInterfaces(); i++) 00781 { 00782 entryIFT = ift->getInterface(i); 00783 insertIft(entryIFT); 00784 } 00785 00786 // zpracovani XML konfigurace pro RIP 00787 hostname = par("hostname"); 00788 const char *fileName = par("configFile"); 00789 if (!LoadConfigFromXML(fileName)) 00790 return; 00791 00792 // sledování klíčových proměnných 00793 WATCH_VECTOR(ripIft); 00794 WATCH_VECTOR(network); 00795 WATCH_VECTOR(routeTimer); 00796 WATCH(redistr); 00797 00798 // zapni hello timer 00799 RIPTimer *msg = new RIPTimer("Hello"); 00800 msg->setTimerKind(hello); 00801 scheduleAt(simTime() + 30.0 + exponential(1), msg); 00802 00803 // vysli requesty vsem sousedum 00804 this->sendPacket(Request, BROADCAST); 00805 } 00806 } 00807 00817 void RIPRouting::handleMessage(cMessage *msg) 00818 { 00819 EV << hostname << "RIPRouting::handleMessage" << endl; 00820 vector<RouteEntry> newEntry; 00821 IPAddress mask; 00822 int size; 00823 int i; 00824 00825 // vlastni zprava, tj. nektery z casovacu 00826 if (msg->isSelfMessage()) 00827 { 00828 RIPTimer *timer = check_and_cast <RIPTimer *> (msg); 00829 switch(timer->getTimerKind()) 00830 { 00831 case hello: 00832 // hello packet (30s) 00833 EV << hostname << ": Prisel hello." << endl; 00834 this->sendPacket(Response, BROADCAST); 00835 updateTimer(hello, NULL); 00836 delete timer; 00837 break; 00838 00839 case timeout: 00840 // vyprsel garbage-collection timer (120s) 00841 EV << hostname << ": Prisel timeout." << endl; 00842 i = getRouteRT(timer); 00843 routeTimer[i].route->setMetric(16); 00844 updateTimer(garbage, &routeTimer[i]); 00845 sendTrigger(); 00846 delete timer; 00847 break; 00848 00849 case garbage: 00850 // vymaz cestu, timout (180s) 00851 EV << hostname << ": Prisel garbage." << endl; 00852 i = getRouteRT(timer); 00853 EV << hostname << ": Vyprsel garbage na adrese: " << routeTimer[i].route->getHost() << endl; 00854 EV << hostname << ": Mazu cestu: " << routeTimer[i].route->info() << endl; 00855 rt->deleteRoute(routeTimer[i].route); 00856 routeTimer.erase(routeTimer.begin() + i); 00857 delete timer; 00858 break; 00859 00860 case trigger: 00861 // hello packet (30s) 00862 EV << "Prisel trigger." << endl; 00863 size = rt->getNumRoutes(); 00864 this->sendPacket(Response, BROADCAST); 00865 delete triggerTimer; 00866 triggerTimer = NULL; 00867 break; 00868 00869 default: 00870 delete timer; 00871 } 00872 } 00873 // cizi RIP zprava 00874 else if (dynamic_cast<RIPPacket *>(msg)) 00875 this->processPacket(msg); 00876 else 00877 EV << "ICMP ERROR nebo jina zprava" << endl; 00878 } 00879 00890 bool RIPRouting::LoadConfigFromXML(const char *filename) 00891 { 00892 // nacteni dokumentu 00893 cXMLElement* asConfig = ev.getXMLDocument(filename); 00894 if (asConfig == NULL) 00895 return false; 00896 00897 // prvni element <Router id="192.168.10.7"> 00898 std::string routerXPath("Router[@id='"); 00899 IPAddress routerId = rt->getRouterId(); 00900 routerXPath += routerId.str(); 00901 routerXPath += "']"; 00902 00903 cXMLElement* routerNode = asConfig->getElementByPath(routerXPath.c_str()); 00904 if (routerNode == NULL) 00905 { 00906 error("No configuration for Router ID: %s", routerId.str().c_str()); 00907 return false; 00908 } 00909 00910 cXMLElement* routingNode = routerNode->getElementByPath("Routing"); 00911 if (routingNode == NULL) 00912 return false; 00913 00914 cXMLElement* ripNode = routingNode->getElementByPath("Rip"); 00915 if (ripNode == NULL) 00916 return false; 00917 00918 // vypis siti, ktere se maji propagovat v RIP zpravach 00919 cXMLElementList childrenNodes = ripNode->getChildrenByTagName("Network"); 00920 if (childrenNodes.size() > 0) 00921 { 00922 for (cXMLElementList::iterator node = childrenNodes.begin(); node != childrenNodes.end(); node++) 00923 { 00924 network.push_back(ULongFromAddressString((*node)->getNodeValue())); 00925 } 00926 } 00927 else 00928 return false; 00929 00930 // vypis pasivnich interfacu, na ktere se nemaji zasilat RIP zpravy 00931 childrenNodes = ripNode->getChildrenByTagName("Passive-interface"); 00932 if (childrenNodes.size() > 0) 00933 { 00934 for (cXMLElementList::iterator node = childrenNodes.begin(); node != childrenNodes.end(); node++) 00935 { 00936 int id = ift->getInterfaceByName((*node)->getNodeValue())->getInterfaceId(); 00937 for (int i = 0; i < (int) ripIft.size(); i++) 00938 { 00939 if (ripIft[i].intID == id) 00940 { 00941 ripIft[i].passive = true; 00942 break; 00943 } 00944 } 00945 } 00946 } 00947 00948 // nacteni elementu redistribuce 00949 cXMLElement* redistrNode = ripNode->getElementByPath("Redistribute"); 00950 if (redistrNode == NULL) 00951 return true; 00952 00953 // nacteni protokolu, ze ktereho se bude redistribuvota (ospf) 00954 cXMLElement* protocolNode = redistrNode->getElementByPath("Protocol"); 00955 if (protocolNode == NULL) 00956 { 00957 error("Pro redistribuci neni definovan protokol."); 00958 return false; 00959 } 00960 else 00961 redistr.protocol = (char *) protocolNode->getNodeValue(); 00962 00963 // nacteni metriky, ktera se priradi cizim cestam 00964 cXMLElement* metricNode = redistrNode->getElementByPath("Metric"); 00965 if (metricNode == NULL) 00966 { 00967 error("Pro redistribuci neni definovana metrika."); 00968 return false; 00969 } 00970 else 00971 redistr.metric = atol(metricNode->getNodeValue()); 00972 00973 redistr.redistrinute = true; 00974 return true; 00975 } 00976 00988 void RIPRouting::receiveChangeNotification(int category, const cPolymorphic *details) 00989 { 00990 // ignoruj notifikaci behem inicializace 00991 if (simulation.getContextType() == CTX_INITIALIZE) 00992 return; 00993 00994 Enter_Method_Silent(); 00995 printNotificationBanner(category, details); 00996 00997 00998 // notifikace na rozhrani 00999 if (category == NF_INTERFACE_STATE_CHANGED) 01000 { 01001 InterfaceEntry *entry = check_and_cast<InterfaceEntry*>(details); 01002 int i = 0; 01003 01004 // Interface je DOWN 01005 if (entry->isDown()) 01006 { 01007 EV << hostname << ": Interface je DOWN\n"; 01008 01009 // vymaz primou cestu z tabulky a uloz ji do struktury intDown 01010 for (i = 0; i < (int) rt->getNumRoutes(); i++) 01011 { 01012 if (rt->getRoute(i)->getType() == INET_API IPRoute::DIRECT) 01013 { 01014 if (rt->getRoute(i)->getInterface() == entry) 01015 { 01016 EV << "Mazu cestu: " << rt->getRoute(i)->info() << endl; 01017 IPRoute *entryRT = new IPRoute(); 01018 //entryRT = const_cast<IPRoute*> (rt->getRoute(i)); 01019 entryRT->setHost(rt->getRoute(i)->getHost()); 01020 entryRT->setGateway(rt->getRoute(i)->getGateway()); 01021 entryRT->setNetmask(rt->getRoute(i)->getNetmask()); 01022 entryRT->setInterface(entry); 01023 entryRT->setType(INET_API IPRoute::DIRECT); 01024 entryRT->setSource(INET_API IPRoute::IFACENETMASK); 01025 entryRT->setMetric(1); 01026 rt->deleteRoute(rt->getRoute(i)); 01027 intDown.push_back(entryRT); 01028 } 01029 } 01030 } 01031 01032 // vymaz cestu i z interni tabulky rozhraní ripIft 01033 for (i = 0; i < (int) ripIft.size(); i++) 01034 { 01035 if (ripIft[i].entry == entry) 01036 ripIft.erase(ripIft.begin() + i); 01037 } 01038 01039 // vzdalene cesty smaz taky 01040 for(i = 0; i < (int) routeTimer.size(); i++) 01041 { 01042 if (routeTimer[i].route->getInterface() == entry) 01043 { 01044 EV << "Mazu cestu: " << routeTimer[i].route->info() << endl; 01045 01046 // zrusit a samzat jeji casovac 01047 if (routeTimer[i].timer->isScheduled()) 01048 cancelEvent(routeTimer[i].timer); 01049 delete routeTimer[i].timer; 01050 01051 // v pripade, ze cesta má dvojici, vymaz zaznam z checkTwin 01052 if (checkTwin(routeTimer[i].route)) 01053 { 01054 for (int j = 0; j < (int) routeTwins.size(); j++) 01055 { 01056 if (routeTimer[i].route == routeTwins[j].route1 || routeTimer[i].route == routeTwins[j].route2) 01057 routeTwins.erase(routeTwins.begin() + j); 01058 } 01059 } 01060 // vymazat cestu a jeji znaznam v routeTimer 01061 rt->deleteRoute(routeTimer[i].route); 01062 routeTimer.erase(routeTimer.begin() + i); 01063 i--; 01064 } 01065 } 01066 } 01067 // Interface je UP 01068 else 01069 { 01070 EV << hostname << ": Interface je UP\n"; 01071 01072 // vlozime zpet do RT prime cesty 01073 for(i = 0; i < (int) intDown.size(); i++) 01074 { 01075 if (intDown[i]->getInterface() == entry) 01076 { 01077 rt->addRoute(intDown[i]); 01078 intDown.erase(intDown.begin() + i); 01079 } 01080 } 01081 // vloz zaznam do ripIft 01082 insertIft(entry); 01083 } 01084 // rozesli aktualizace 01085 sendTrigger(); 01086 } 01087 } 01088 01098 vector<RouteEntry> RIPRouting::getOSPFRoutes() 01099 { 01100 // redistribujeme z protokolu OSPF? 01101 vector<RouteEntry> newEntry; // vektor zasilanych adres 01102 if (strcmp(redistr.protocol, "ospf")) 01103 return newEntry; 01104 01105 // proměnné 01106 IPRoute *entryRT = new IPRoute(); // routovaci tabulka 01107 int sizeTab = rt->getNumRoutes(); // velikost routovací tabulky 01108 RouteEntry entry; // nova polozka s adresou 01109 01110 // ber postupne site z routovaci tabulky a kontroluj je 01111 for (int i = 0; i < sizeTab; i++) 01112 { 01113 entryRT = const_cast<IPRoute*>(rt->getRoute(i)); 01114 if (entryRT->getSource() == INET_API IPRoute::OSPF) 01115 { 01116 // pridava RIP cestu 01117 entry.addressID = 2; 01118 entry.mustBeZero2 = 0; 01119 entry.mustBeZero3 = 0; 01120 entry.mustBeZero4 = 0; 01121 entry.ipAddress = entryRT->getHost(); 01122 EV << "Posilam podle RIP zaznamu IP: " << entry.ipAddress << endl; 01123 entry.metric = redistr.metric; 01124 newEntry.push_back(entry); 01125 continue; 01126 } 01127 } 01128 01129 return newEntry; 01130 }