|
INET Framework for OMNeT++/OMNEST
|
00001 // IGMP.cc 00002 // Petr Matelesko 00003 // 5. 5. 2010 00004 00005 #include "IGMP.h" 00006 00007 #ifndef WITHOUT_IPv4 00008 #include "IPv4InterfaceData.h" 00009 #endif 00010 00011 Define_Module(IGMP); 00012 00014 std::ostream& operator<<(std::ostream& os, const IGMPInterface& e) 00015 { 00016 os << "Internet address is " << e.ie->ipv4Data()->getIPAddress() << "/" << e.ie->ipv4Data()->getNetmask().getNetmaskLength() << endl; 00017 os << "IGMP is enabled on interface" << endl; 00018 os << "Curent IGMP version is 2" << endl; 00019 // os << "IGMP query interval is " << IGMP::QUERY_INTERVAL << " seconds" << endl; 00020 // os << "IGMP querier timeout is " << IGMP::OTHER_QUERIER_PRESENT_INTERVAL << " seconds" << endl; 00021 // os << "IGMP max query response time is " << IGMP::QUERY_RESPONSE_INTERVAL_SEC << " seconds" << endl; 00022 // os << "Last member query response interval is " << IGMP::QUERY_RESPONSE_INTERVAL_SEC / 1000 << " ms" << endl; 00023 // os << "IGMP activity: " << e.join << " joins, " << e.leave << " leaves" << endl; 00024 os << "IGMP querying router is " << e.ipQuerier; 00025 if (e.querier) 00026 os << " (this system)"; 00027 os << endl; 00028 00029 return os; 00030 }; 00031 00039 bool IGMP::isRouter() 00040 { 00041 cModule *parentModule = this->getParentModule()->getParentModule(); 00042 00043 std::string moduleName = parentModule->getNedTypeName(); 00044 00045 if (moduleName.find("router") != std::string::npos || moduleName.find("Router") != std::string::npos) 00046 return true; 00047 else 00048 return false; 00049 } 00050 00061 IPAddress IGMP::getQuerierAddress(IPAddress thisRouterAddress, IPAddress otherRouterAddress) 00062 { 00063 if (otherRouterAddress < thisRouterAddress) 00064 return otherRouterAddress; 00065 else 00066 return thisRouterAddress; 00067 } 00068 00077 int IGMP::getIGMPInterfaceByID(int interfaceID) 00078 { 00079 for (int i = 0; i < (int)igmpIft.size(); i++) 00080 { 00081 if (igmpIft[i].intID == interfaceID) 00082 return i; 00083 } 00084 return -1; 00085 } 00086 00096 int IGMP::getGroupMembershipPosition(IPAddress groupAddress, IGMPInterface * igmpInterface) 00097 { 00098 00099 int n = igmpInterface->groupMembershipTable.size(); 00100 for (int j = 0; j < n; j++) 00101 { 00102 if (groupAddress.equals(igmpInterface->groupMembershipTable[j].multicastGroup)) 00103 return j; 00104 } 00105 return -1; 00106 } 00107 00118 IGMPMessage *IGMP::createPacket(int type, int maxRespTime, IPAddress groupAddress) 00119 { 00120 00121 IGMPMessage *msg = new IGMPMessage(); 00122 00123 switch (type) { 00124 00125 case IGMP_MEMBERSHIP_QUERY: 00126 msg->setName("IGMP_MEMBERSHIP_QUERY"); 00127 break; 00128 00129 case IGMP_MEMBERSHIP_REPORT_V1: 00130 msg->setName("IGMP_MEMBERSHIP_REPORT_V1"); 00131 break; 00132 00133 case IGMP_MEMBERSHIP_REPORT_V2: 00134 msg->setName("IGMP_MEMBERSHIP_REPORT_V2"); 00135 break; 00136 00137 case IGMP_LEAVE_GROUP: 00138 msg->setName("IGMP_LEAVE_GROUP"); 00139 break; 00140 00141 } 00142 00143 msg->setType(type); 00144 msg->setMaxRespTime(maxRespTime); 00145 msg->setGroupAddress(groupAddress); 00146 00147 return msg; 00148 } 00149 00150 00163 void IGMP::sendMembershipGeneralQuery(int interfaceID) 00164 { 00165 IGMPMessage *msg = createPacket(IGMP_MEMBERSHIP_QUERY, QUERY_RESPONSE_INTERVAL_SEC, IPAddress::UNSPECIFIED_ADDRESS); 00166 00167 IPControlInfo *controlInfo = new IPControlInfo(); 00168 controlInfo->setDestAddr(IPAddress::ALL_HOSTS_MCAST); 00169 controlInfo->setProtocol(IP_PROT_IGMP); 00170 controlInfo->setTimeToLive(1); 00171 controlInfo->setInterfaceId(interfaceID); 00172 msg->setControlInfo(controlInfo); 00173 00174 send(msg, "sendOut"); 00175 } 00176 00189 void IGMP::sendMembershipGroupSpecificQuery(IPAddress groupAddress, int interfaceID) 00190 { 00191 IGMPMessage *msg = createPacket(IGMP_MEMBERSHIP_QUERY, LAST_MEMBER_QUERY_INTERVAL_SEC, groupAddress); 00192 00193 IPControlInfo *controlInfo = new IPControlInfo(); 00194 controlInfo->setDestAddr(groupAddress); 00195 controlInfo->setProtocol(IP_PROT_IGMP); 00196 controlInfo->setTimeToLive(1); 00197 controlInfo->setInterfaceId(interfaceID); 00198 msg->setControlInfo(controlInfo); 00199 00200 send(msg, "sendOut"); 00201 } 00202 00216 void IGMP::sendMembershipReportV2(IPAddress groupAddress, int interfaceID) 00217 { 00218 IGMPMessage *msg = createPacket(IGMP_MEMBERSHIP_REPORT_V2, 0, groupAddress); 00219 00220 IPControlInfo *controlInfo = new IPControlInfo(); 00221 controlInfo->setDestAddr(groupAddress); 00222 controlInfo->setProtocol(IP_PROT_IGMP); 00223 controlInfo->setTimeToLive(1); 00224 controlInfo->setInterfaceId(interfaceID); 00225 msg->setControlInfo(controlInfo); 00226 00227 send(msg, "sendOut"); 00228 } 00229 00243 void IGMP::sendLeaveGroup(IPAddress groupAddress, int interfaceID) 00244 { 00245 IGMPMessage *msg = createPacket(IGMP_LEAVE_GROUP, 0, groupAddress); 00246 00247 IPControlInfo *controlInfo = new IPControlInfo(); 00248 controlInfo->setDestAddr(IPAddress::ALL_ROUTERS_MCAST); 00249 controlInfo->setProtocol(IP_PROT_IGMP); 00250 controlInfo->setTimeToLive(1); 00251 controlInfo->setInterfaceId(interfaceID); 00252 msg->setControlInfo(controlInfo); 00253 00254 send(msg, "sendOut"); 00255 } 00256 00266 void IGMP::addGroupToInterface(const int interfaceID, const IPAddress groupAddress) 00267 { 00268 IPv4InterfaceData::IPAddressVector addr; // vektor IP adres 00269 int i = getIGMPInterfaceByID(interfaceID); 00270 00271 // ziska ukazatel na ipv4 data rozhrani 00272 IPv4InterfaceData *ipv4 = igmpIft[i].ie->ipv4Data(); 00273 00274 // pokud neni adresa multicastove skupiny v rozhrani, zapiseme ji 00275 int n = ipv4->getMulticastGroups().size(); 00276 for (int j = 0; j < n; j++) 00277 { 00278 if (groupAddress.equals(ipv4->getMulticastGroups()[j])) 00279 return; 00280 } 00281 addr = ipv4->getMulticastGroups(); 00282 addr.push_back(groupAddress); 00283 ipv4->setMulticastGroups(addr); 00284 } 00285 00295 void IGMP::removeGroupFromInterface(const int interfaceID, const IPAddress groupAddress) 00296 { 00297 IPv4InterfaceData::IPAddressVector addr; // vektor IP adres 00298 int i = getIGMPInterfaceByID(interfaceID); 00299 00300 // ziska ukazatel na ipv4 data rozhrani 00301 IPv4InterfaceData *ipv4 = igmpIft[i].ie->ipv4Data(); 00302 00303 // pokud nalezneme danou multicastovou adresu, odstranime ji 00304 addr = ipv4->getMulticastGroups(); 00305 00306 int n = addr.size(); 00307 for (int j = 0; j < n; j++) 00308 { 00309 if (groupAddress.equals(addr[j])) 00310 { 00311 addr.erase(addr.begin() + j); 00312 ipv4->setMulticastGroups(addr); 00313 return; 00314 } 00315 } 00316 00317 } 00318 00326 void IGMP::processMembershipReportV2(IGMPMessage *msg) 00327 { 00328 EV << "ProcessMembershipReportV2()" << endl; 00329 00330 IPAddress groupAddress; // skupinova adresa 00331 IPAddress lastReporter; // zdrojova IP adresa klienta 00332 int intID; // ID rozhrani 00333 int i; 00334 00335 /* Ziskani skupiny */ 00336 groupAddress = msg->getGroupAddress(); 00337 00338 /* zjistit z ktereho rozhrani zprava prisla a IP adresa klienta */ 00339 if (dynamic_cast<IPControlInfo *>(msg->getControlInfo())!=NULL) 00340 { 00341 IPControlInfo *controlInfo = (IPControlInfo *)msg->getControlInfo(); 00342 lastReporter = controlInfo->getSrcAddr(); 00343 intID = controlInfo->getInterfaceId(); 00344 } 00345 00346 // pridat info na dane rozrhrani o skupine 00347 addGroupToInterface(intID, groupAddress); 00348 00349 i = getIGMPInterfaceByID(intID); 00350 // zapni casovac clenstvi na skupinach 00351 startGroupMembershipTimer(&igmpIft[i], groupAddress, lastReporter, GROUP_MEMBERSHIP_INTERVAL); 00352 00353 // pokud existuje casovac Last Member, tak ho zrus 00354 int j = getGroupMembershipPosition(groupAddress, &igmpIft[i]); 00355 if (igmpIft[i].groupMembershipTable[j].lastMember != NULL && igmpIft[i].groupMembershipTable[j].lastMember->isScheduled()) 00356 { 00357 cancelEvent(igmpIft[i].groupMembershipTable[j].lastMember); 00358 delete igmpIft[i].groupMembershipTable[j].lastMember; 00359 igmpIft[i].groupMembershipTable[j].lastMember = NULL; 00360 } 00361 00362 // TODO notify routing - spoluprace s PIM 00363 00364 delete msg; 00365 } 00366 00367 00368 void IGMP::processLeaveGroup(IGMPMessage *msg) 00369 { 00370 EV << "processLeaveGroup()" << endl; 00371 00372 IPAddress groupAddress; // skupinova adresa 00373 IPAddress lastReporter; // zdrojova IP adresa klienta 00374 int intID; // ID rozhrani 00375 int i; 00376 int j; 00377 00378 /* Ziskani skupiny */ 00379 groupAddress = msg->getGroupAddress(); 00380 00381 /* zjistit z ktereho rozhrani zprava prisla a IP adresa klienta */ 00382 if (dynamic_cast<IPControlInfo *>(msg->getControlInfo())!=NULL) 00383 { 00384 IPControlInfo *controlInfo = (IPControlInfo *)msg->getControlInfo(); 00385 lastReporter = controlInfo->getSrcAddr(); 00386 intID = controlInfo->getInterfaceId(); 00387 } 00388 00389 i = getIGMPInterfaceByID(intID); 00390 00391 /* Pokud je rozhrani non-querier, tak zpravu zahodime */ 00392 if (!igmpIft[i].querier) { 00393 delete msg; 00394 return; 00395 } 00396 00397 // pozadovana skupina neni v tabulce, zpravu zahodime 00398 if ((j = getGroupMembershipPosition(groupAddress, &igmpIft[i])) == -1) 00399 { 00400 delete msg; 00401 return; 00402 } 00403 00404 // - posle na dany inteface zpravu Membership Query - Group-Specific Query 00405 // - nastavi timer clenstvi ve skupine na LAST_MEMBER_QUERIER_INETERVAL 00406 // - nastavi timer pro opakovani Group-Specific Query 00407 startGroupMembershipTimer(&igmpIft[i], groupAddress, igmpIft[i].groupMembershipTable[j].lastReporter, LAST_MEMBER_QUERIER_INETERVAL); 00408 startLastMemberTimer(&igmpIft[i], groupAddress); 00409 sendMembershipGroupSpecificQuery(groupAddress, intID); 00410 00411 delete msg; 00412 } 00413 00414 00422 void IGMP::processMembershipQuery(IGMPMessage *msg) 00423 { 00424 //EV << "ProcessMembershipQuery()" << endl; // DEBUG 00425 00426 IPAddress srcAddr; 00427 IPAddress myAddr; 00428 IPAddress querierAddr; 00429 int intID; 00430 int i; 00431 00432 /* zjistit z ktereho rozhrani zprava prisla a IP adresa klienta */ 00433 if (dynamic_cast<IPControlInfo *>(msg->getControlInfo()) != NULL) 00434 { 00435 IPControlInfo *controlInfo = (IPControlInfo *)msg->getControlInfo(); 00436 srcAddr = controlInfo->getSrcAddr(); 00437 intID = controlInfo->getInterfaceId(); 00438 } 00439 00440 i = getIGMPInterfaceByID(intID); 00441 myAddr = igmpIft[i].ie->ipv4Data()->getIPAddress(); 00442 00443 // testuju, jestli jsem non-querier 00444 querierAddr = getQuerierAddress(myAddr, srcAddr); 00445 00446 if (querierAddr != myAddr) 00447 { 00448 //EV << "non-querier" << endl; // DEBUG 00449 00450 // zmenim stav na non-querier 00451 igmpIft[i].querier = false; 00452 igmpIft[i].ipQuerier = querierAddr; 00453 00454 // pokud existuje, zrusime casovac General Query Init 00455 if (igmpIft[i].initGeneralQuery != NULL && igmpIft[i].initGeneralQuery->isScheduled()) 00456 { 00457 cancelEvent(igmpIft[i].initGeneralQuery); 00458 delete igmpIft[i].initGeneralQuery; 00459 igmpIft[i].initGeneralQuery = NULL; 00460 } 00461 00462 // pokud existuje, zrusime casovac General Query 00463 if (igmpIft[i].generalQuery != NULL && igmpIft[i].generalQuery->isScheduled()) 00464 { 00465 cancelEvent(igmpIft[i].generalQuery); 00466 delete igmpIft[i].generalQuery; 00467 igmpIft[i].generalQuery = NULL; 00468 } 00469 00470 // spustime casovac Other Querier Present 00471 startInterfaceTimer(TIMER_OTHER_QUERIER_PRESENT, &igmpIft[i]); 00472 00473 } 00474 00475 delete msg; 00476 } 00477 00478 00486 void IGMP::processIGMPMessage(IGMPMessage *igmpmsg) 00487 { 00488 switch (igmpmsg->getType()) 00489 { 00490 case IGMP_MEMBERSHIP_QUERY: 00491 processMembershipQuery(igmpmsg); 00492 break; 00493 00494 case IGMP_MEMBERSHIP_REPORT_V2: 00495 processMembershipReportV2(igmpmsg); 00496 break; 00497 00498 case IGMP_LEAVE_GROUP: 00499 processLeaveGroup(igmpmsg); 00500 break; 00501 default: 00502 EV << "processIGMPMesage(): Unknow IGMP Message" << endl; 00503 } 00504 } 00505 00513 void IGMP::processIGMPTimer(IGMPTimer *timer) 00514 { 00515 int i; // index v tabulce IGMP rozhrani 00516 i = getIGMPInterfaceByID(timer->getIntID()); 00517 00518 switch (timer->getTimerKind()) 00519 { 00520 case TIMER_INIT_GENERAL_QUERY: 00521 // Casovac Init General Query vyprsel - 00522 // - posle General Query 00523 // - pokud jsme poslali vsechny Init General Query (STARTUP_QUERY_COUNT) 00524 // -- nastavi casovac General Query 00525 // - pokud jsme jeste vsechny Init General Query neposlali 00526 // -- nastavi casovac Init General Query 00527 sendMembershipGeneralQuery(timer->getIntID()); 00528 00529 if ((timer->getCount() - 1) > 0) 00530 startInterfaceTimer(TIMER_INIT_GENERAL_QUERY, &igmpIft[i]); 00531 else 00532 startInterfaceTimer(TIMER_GENERAL_QUERY, &igmpIft[i]); 00533 break; 00534 00535 case TIMER_GENERAL_QUERY: 00536 // Casovac General Query vyprsel - 00537 // - posle zpravu General Query a nastavi casovac General Query 00538 sendMembershipGeneralQuery(timer->getIntID()); 00539 startInterfaceTimer(TIMER_GENERAL_QUERY, &igmpIft[i]); 00540 break; 00541 00542 case TIMER_OTHER_QUERIER_PRESENT: 00543 // Casovac pritomnosti jineho Querier routeru vyprsel - 00544 // - rozhrani se stava opet Querierem 00545 // - posle zpravu General Query a nastavi casovac General Query 00546 igmpIft[i].querier = true; 00547 igmpIft[i].ipQuerier = igmpIft[i].ie->ipv4Data()->getIPAddress(); 00548 igmpIft[i].otherQuerierPresent = NULL; 00549 sendMembershipGeneralQuery(timer->getIntID()); 00550 startInterfaceTimer(TIMER_GENERAL_QUERY, &igmpIft[i]); 00551 break; 00552 00553 case TIMER_GROUP_MEMBERSHIP: 00554 // Casovac clenstvi vyprsel: 00555 // - odebereme multicasatovou skupiny z tabulky rozhrani 00556 // - odstranime zaznam ve vlastni tabulce clenstvi 00557 removeGroupFromInterface(timer->getIntID(), timer->getGroupAddress()); 00558 00559 int j; 00560 j = getGroupMembershipPosition(timer->getGroupAddress(), &igmpIft[i]); 00561 00562 igmpIft[i].groupMembershipTable.erase(igmpIft[i].groupMembershipTable.begin() + j); 00563 00564 // TODO - notify routing - spoluprace s PIM 00565 break; 00566 00567 case TIMER_LAST_MEMBER: 00568 00569 sendMembershipGroupSpecificQuery(timer->getGroupAddress(), timer->getIntID()); 00570 00571 if ((timer->getCount() - 1) > 0) 00572 startLastMemberTimer(&igmpIft[i], timer->getGroupAddress()); 00573 00574 break; 00575 } 00576 delete timer; 00577 00578 } 00579 00588 void IGMP::handleMessage(cMessage *msg) 00589 { 00590 /* Implementace IGMP na routeru */ 00591 if (isRouter()) 00592 { 00593 //EV << "IGMP::handleMessage(): on router" << endl; // DEBUG 00594 00595 /* zpracovani vlastnich zprav - timeru */ 00596 if (msg->isSelfMessage()) 00597 { 00598 processIGMPTimer(check_and_cast<IGMPTimer *>(msg)); 00599 00600 00601 } 00602 /* zpracovani IGMP zprav */ 00603 else 00604 { 00605 processIGMPMessage(check_and_cast<IGMPMessage *>(msg)); 00606 } 00607 00608 } 00609 /* Implementace IGMP na hostu */ 00610 else 00611 { 00612 //EV << "IGMP::handleMessage(): on host" << endl; // DEBUG 00613 00614 /* vlastni zpravy */ 00615 if (msg->isSelfMessage()) 00616 { 00617 // FIXME zatim zadne vlastni zpravy 00618 } 00619 /* IGMP zpravy */ 00620 else 00621 { 00622 IGMPMessage *mymsg = check_and_cast<IGMPMessage *>(msg); 00623 00624 switch (mymsg->getType()) 00625 { 00626 case IGMP_MEMBERSHIP_QUERY: 00627 00628 if (dynamic_cast<IPControlInfo *>(mymsg->getControlInfo())!=NULL) 00629 { 00630 IPControlInfo *controlInfo = (IPControlInfo *)mymsg->removeControlInfo(); 00631 EV << "IGMP_MEMBERSHIP_QUERY from " << controlInfo->getSrcAddr() << " to " << controlInfo->getDestAddr() << endl; // FIXME destAddr nevzyplnuje 00632 00633 delete controlInfo; 00634 } 00635 00636 break; 00637 } 00638 00639 delete mymsg; 00640 00641 } 00642 00643 } 00644 00645 } 00646 00657 IGMPTimer * IGMP::startGroupMembershipTimer(IGMPInterface * igmpInterface, IPAddress groupAddress, IPAddress lastReporter, int interval) 00658 { 00659 IGMPTimer *newTimer = new IGMPTimer(); 00660 newTimer->setTimerKind(TIMER_GROUP_MEMBERSHIP); 00661 newTimer->setName("Timer Group Membership"); 00662 newTimer->setIntID(igmpInterface->intID); 00663 newTimer->setGroupAddress(groupAddress); 00664 scheduleAt(simTime() + interval, newTimer); 00665 00666 // prohledame tabulku clenstvi, pokud uz clenstvi existuje: 00667 // - zrusime stary timer 00668 // - zapiseme novy 00669 // - zapiseme noveho Last Reportera 00670 00671 int j = getGroupMembershipPosition(groupAddress, igmpInterface); 00672 00673 if (j != -1) 00674 { 00675 cancelEvent(igmpInterface->groupMembershipTable[j].groupMembership); 00676 delete igmpInterface->groupMembershipTable[j].groupMembership; 00677 igmpInterface->groupMembershipTable[j].lastReporter = lastReporter; 00678 igmpInterface->groupMembershipTable[j].groupMembership = newTimer; 00679 igmpInterface->groupMembershipTable[j].lastMember = NULL; 00680 return newTimer; 00681 } 00682 00683 // pokud timer neexistuje, vytvorime nove clenstvi 00684 // - zapiseme vsechny hodnoty 00685 // - vlozime do tabulky clenstvi 00686 IGMPGroupMembership newGroupMembership; 00687 newGroupMembership.multicastGroup = groupAddress; 00688 newGroupMembership.lastReporter = lastReporter; 00689 newGroupMembership.groupMembership = newTimer; 00690 newGroupMembership.lastMember = NULL; 00691 igmpInterface->groupMembershipTable.push_back(newGroupMembership); 00692 00693 return newTimer; 00694 } 00695 00704 IGMPTimer * IGMP::startLastMemberTimer(IGMPInterface * igmpInterface, IPAddress groupAddress) 00705 { 00706 IGMPTimer *newTimer = new IGMPTimer(); 00707 newTimer->setTimerKind(TIMER_LAST_MEMBER); 00708 newTimer->setName("Timer Last Member"); 00709 newTimer->setIntID(igmpInterface->intID); 00710 newTimer->setGroupAddress(groupAddress); 00711 scheduleAt(simTime() + LAST_MEMBER_QUERY_INTERVAL_SEC, newTimer); 00712 00713 // vytvoreni prvotniho timeru - 00714 // - pocet Group-Specific Query dle LAST_MEMBER_QUERY_COUNT 00715 00716 int j = getGroupMembershipPosition(groupAddress, igmpInterface); 00717 00718 if (j != -1 && igmpInterface->groupMembershipTable[j].lastMember == NULL) 00719 newTimer->setCount(LAST_MEMBER_QUERY_COUNT - 1); 00720 // u dalsich timeru snizujeme pocet o 1 00721 else 00722 newTimer->setCount(igmpInterface->initGeneralQuery->getCount() - 1); 00723 00724 igmpInterface->groupMembershipTable[j].lastMember = newTimer; 00725 00726 return newTimer; 00727 } 00728 00738 IGMPTimer * IGMP::startInterfaceTimer(int timerType, IGMPInterface * igmpInterface) 00739 { 00740 IGMPTimer *newTimer = new IGMPTimer(); 00741 newTimer->setTimerKind(timerType); 00742 newTimer->setIntID(igmpInterface->intID); 00743 00744 switch (timerType) 00745 { 00746 case TIMER_INIT_GENERAL_QUERY: 00747 00748 // vytvoreni prvotniho timeru - 00749 // - pocet initializacnich General Query dle STARTUP_QUERY_COUNT 00750 if (igmpInterface->initGeneralQuery == NULL) 00751 newTimer->setCount(STARTUP_QUERY_COUNT - 1); 00752 // u dalsich timeru snizujeme pocet o 1 00753 else 00754 newTimer->setCount(igmpInterface->initGeneralQuery->getCount() - 1); 00755 00756 newTimer->setName("Timer Init General Query"); 00757 scheduleAt(simTime() + STARTUP_QUERY_INTERVAL, newTimer); 00758 igmpInterface->initGeneralQuery = newTimer; 00759 break; 00760 00761 case TIMER_GENERAL_QUERY: 00762 newTimer->setName("Timer General Query"); 00763 scheduleAt(simTime() + QUERY_INTERVAL, newTimer); 00764 igmpInterface->generalQuery = newTimer; 00765 break; 00766 00767 case TIMER_OTHER_QUERIER_PRESENT: 00768 // pokud uz nejaky timer bezi, tak ho zrusime 00769 if (igmpInterface->otherQuerierPresent != NULL && igmpInterface->otherQuerierPresent->isScheduled()) 00770 { 00771 cancelEvent(igmpInterface->otherQuerierPresent); 00772 delete igmpInterface->otherQuerierPresent; 00773 } 00774 // vytvorime novy timer 00775 newTimer->setName("Timer Other Querier Present"); 00776 scheduleAt(simTime() + OTHER_QUERIER_PRESENT_INTERVAL, newTimer); 00777 igmpInterface->otherQuerierPresent = newTimer; 00778 break; 00779 } 00780 return newTimer; 00781 } 00782 00790 void IGMP::initialize(int stage) 00791 { 00792 if (stage == 4) 00793 { 00794 /* IGMP modul routeru */ 00795 if (isRouter()) 00796 { 00797 /* pristup k tabulce rozhrani */ 00798 ift = InterfaceTableAccess().get(); 00799 00800 /* inicializace timeru a promennych */ 00801 00802 ROBUSTNESS_VARIABLE = 2; // default: 2 00803 QUERY_INTERVAL = 125; // default: 125 s 00804 QUERY_RESPONSE_INTERVAL = 100; // default: 100 = 10 s 00805 QUERY_RESPONSE_INTERVAL_SEC = QUERY_RESPONSE_INTERVAL / 10; // prevod na sekundy 00806 LAST_MEMBER_QUERY_COUNT = ROBUSTNESS_VARIABLE; 00807 LAST_MEMBER_QUERY_INTERVAL = 10; // default: 10 = 1 s 00808 LAST_MEMBER_QUERY_INTERVAL_SEC = LAST_MEMBER_QUERY_INTERVAL / 10; // prevod na sekundy 00809 LAST_MEMBER_QUERIER_INETERVAL = LAST_MEMBER_QUERY_COUNT * LAST_MEMBER_QUERY_INTERVAL_SEC; 00810 GROUP_MEMBERSHIP_INTERVAL = (ROBUSTNESS_VARIABLE * QUERY_INTERVAL) + QUERY_RESPONSE_INTERVAL_SEC; 00811 STARTUP_QUERY_COUNT = ROBUSTNESS_VARIABLE; 00812 STARTUP_QUERY_INTERVAL = QUERY_INTERVAL / 4; 00813 OTHER_QUERIER_PRESENT_INTERVAL = (ROBUSTNESS_VARIABLE * QUERY_INTERVAL) + (QUERY_RESPONSE_INTERVAL_SEC / 2); 00814 00815 /* naplneni vlastni tabulky rozhrani aktivni IGMP */ 00816 // - neni loopback 00817 // - kazde rozhrani je automaticky Querier 00818 // - casovace nejsou nastaveny 00819 // TODO: 00820 // - ted je IGMP na vsech rozhranich defaultne zaple 00821 // - dodelat zapinani IGMP na rozhrani spolu s PIMem 00822 00823 for (int i = 0; i < ift->getNumInterfaces(); i++) 00824 { 00825 if (!ift->getInterface(i)->isLoopback()) 00826 { 00827 IGMPInterface igmpInt; 00828 igmpInt.intID = ift->getInterface(i)->getInterfaceId(); // interface ID 00829 igmpInt.ie = ift->getInterface(i); // interface entry 00830 igmpInt.querier = true; // querier 00831 igmpInt.ipQuerier = igmpInt.ie->ipv4Data()->getIPAddress(); // IP adresa Queriera 00832 igmpInt.initGeneralQuery = NULL; // casovac init general query 00833 igmpInt.generalQuery = NULL; // casovac general query 00834 igmpInt.otherQuerierPresent = NULL; // casova other querier present 00835 igmpIft.push_back(igmpInt); 00836 00837 } 00838 } 00839 00840 /* sledovani promennych */ 00841 00842 //WATCH_VECTOR(igmpIft[i].groupMembershipTable); 00843 WATCH_VECTOR(igmpIft); 00844 00845 /* startup query */ 00846 // na vsechny rozhrani v tabulce IGMP rozhrani posle General Query a spusti casovac General Query Init 00847 for (int j = 0; j < (int)igmpIft.size(); j++) 00848 { 00849 startInterfaceTimer(TIMER_INIT_GENERAL_QUERY, &igmpIft[j]); 00850 //sendMembershipGeneralQuery(igmpIft[j].intID); 00851 } 00852 00853 } 00854 00855 00856 /* IGMP modul hostu */ 00857 /*else 00858 { 00859 //EV << "IGMP::initialize() on client" << endl; // DEBUG 00860 00861 // TEST: pro testovani chovani 00862 int intID; 00863 ift = InterfaceTableAccess().get(); 00864 00865 00866 IPAddress ga1("225.0.0.1"); 00867 IPAddress ga2("225.0.0.2"); 00868 IPAddress ga3("225.0.0.3"); 00869 IPAddress ga4("225.0.0.4"); 00870 00871 00872 for (int i = 0; i < ift->getNumInterfaces(); i++) 00873 { 00874 if (!ift->getInterface(i)->isLoopback()) 00875 { 00876 intID = ift->getInterface(i)->getInterfaceId(); 00877 break; 00878 } 00879 } 00880 00881 // test 1: join 225.0.0.1 00882 sendMembershipReportV2(ga1, intID); 00883 00884 // test 2. joing 225.0.0.2 - prihlaseni dalsi skupiny 00885 sendMembershipReportV2(ga2, intID); // join 225.0.0.2 00886 00887 // test 3: join 225.0.0.2 - na skupinu, ktere uz je clenem 00888 sendMembershipReportV2(ga2, intID); 00889 00890 00891 // test 4: leave 225.0.0.1 00892 sendLeaveGroup(ga1, intID); // leave 225.0.0.1 00893 00894 // test 5: leave 225.0.0.3 - odhlaseni neprihlasene skupiny 00895 sendLeaveGroup(ga3, intID); // leave 225.0.0.3 00896 00897 // 00898 // sendMembership 00899 00900 // test 6: odhlaseni skupiny 225.0.0.2 po vyprseni casovace 00901 // - neposilame zadnou zpravu 00902 00903 }*/ 00904 } 00905 00906 }