|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Marek Cerny, 2MSK 00003 // FIT VUT 2011 00004 // 00005 // 00006 // This program is free software: you can redistribute it and/or modify 00007 // it under the terms of the GNU Lesser General Public License as published by 00008 // the Free Software Foundation, either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with this program. If not, see http://www.gnu.org/licenses/. 00018 // 00019 00020 #include "ansaMessageHandler6.h" 00021 #include "ansaOspfInterface6.h" 00022 #include "ansaOspfRouting6.h" 00023 00024 #include "ansaOspfTimer6_m.h" 00025 00026 00027 00028 Define_Module(AnsaOspfRouting6); 00029 00030 00031 AnsaOspfRouting6::AnsaOspfRouting6(){ 00032 ospfEnabled = false; 00033 } 00034 00035 AnsaOspfRouting6::~AnsaOspfRouting6(void){ 00036 if (ospfEnabled){ 00037 std::map<AnsaOspf6::ProcessID, AnsaOspf6::Router *>::iterator it; 00038 for (it = routers.begin(); it != routers.end(); it++){ 00039 delete it->second; 00040 } 00041 routers.clear(); 00042 } 00043 } 00044 00045 void AnsaOspfRouting6::initialize(int stage){ 00046 00047 // stage 0 - register for receiving notifications 00048 if (stage == 0){ 00049 00050 nb = NotificationBoardAccess().get(); 00051 if (nb == NULL){ 00052 throw cRuntimeError("NotificationBoard not found"); 00053 } 00054 00055 nb->subscribe(this, NF_INTERFACE_STATE_CHANGED); 00056 00057 00058 // stage 3 - load config from XML and create routers/areas/interfaces 00059 }else if (stage == 3){ 00060 00061 ift = AnsaInterfaceTableAccess().get(); 00062 if (ift == NULL){ 00063 throw cRuntimeError("AnsaInterfaceTable not found"); 00064 } 00065 00066 const char *deviceType = par("deviceType"); 00067 const char *deviceId = par("deviceId"); 00068 const char *configFile = par("configFile"); 00069 00070 cXMLElement *device = xmlParser::GetDevice(deviceType, deviceId, configFile); 00071 if (device == NULL){ 00072 ev << "OSPFv3 is not enabled on this device (" << deviceType << " id=" << deviceId << ")" << endl; 00073 return; 00074 } 00075 00076 00077 cXMLElement *process = xmlParser::GetOspfProcess6(NULL, device); 00078 if (process == NULL){ 00079 ev << "OSPFv3 is not enabled on this device (" << deviceType << " id=" << deviceId << ")" << endl; 00080 return; 00081 } 00082 loadOspfRouting(process); 00083 00084 00085 iface2Routers.resize(ift->getNumInterfaces()); 00086 for (int i = 0; i < ift->getNumInterfaces(); i++){ 00087 iface2Routers[i] = NULL; 00088 } 00089 00090 cXMLElement *iface = xmlParser::GetInterface(NULL, device); 00091 if (iface == NULL && ospfEnabled){ 00092 ev << "OSPFv3 enabled but no interface configuration found? (" << deviceType << " id=" << deviceId << ")" << endl; 00093 } 00094 loadInterfaceConfig(iface); 00095 00096 addWatches(); 00097 00098 00099 // stage 4 - start OSPF processes 00100 }else if (stage == 4){ 00101 00102 if (ospfEnabled){ 00103 00104 InterfaceEntry *firstIface = ift->getFirstInterface(); 00105 if (firstIface == NULL){ 00106 return; 00107 } 00108 int firstIfaceId = firstIface->getInterfaceId(); 00109 00110 // for each interface in interface list 00111 for (int i = 0; i < iface2Routers.size(); i++){ 00112 00113 Router *router = iface2Routers[i]; 00114 if (router == NULL){ 00115 continue; 00116 } 00117 00118 Interface *iface = router->GetNonVirtualInterface(i+firstIfaceId); 00119 if (iface == NULL){ 00120 continue; 00121 } 00122 00123 // trigger startup interface event 00124 iface->ProcessEvent(AnsaOspf6::Interface::InterfaceUp); 00125 } 00126 } 00127 } 00128 } 00129 00130 00131 void AnsaOspfRouting6::handleMessage(cMessage *msg){ 00132 00133 // this is regular (OSPF?) message 00134 if (!msg->isSelfMessage()){ 00135 00136 if (!ospfEnabled){ 00137 ev << "OSPFv3 is not enabled on this device" << endl; 00138 delete msg; 00139 return; 00140 } 00141 00142 // get control info so we can find out from which interface the message arrived 00143 check_and_cast<OspfPacket6*> (msg); 00144 IPv6ControlInfo *info6 = (IPv6ControlInfo *) msg->getControlInfo(); 00145 00146 // get router by interface ID 00147 AnsaOspf6::Router *ospfRouter = getOspfRouter(info6->getInterfaceId()); 00148 00149 // retransmit the message 00150 if (ospfRouter == NULL){ 00151 ev << "OSPFv3 routing is not enabled on this interface (" << info6->getInterfaceId() << ")" << endl; 00152 delete msg; 00153 }else{ 00154 ev << "OSPFv3 module received an OSPF packet! " << endl; 00155 ospfRouter->GetMessageHandler()->MessageReceived(msg); 00156 } 00157 00158 // this is one of the timer-messages 00159 }else{ 00160 00161 // we need to find out which object originated the timer 00162 // and get it's parent Router object 00163 OspfTimer6* timer = check_and_cast<OspfTimer6 *> (msg); 00164 AnsaOspf6::Router *router = NULL; 00165 AnsaOspf6::Area *area = NULL; 00166 AnsaOspf6::Interface *interface = NULL; 00167 AnsaOspf6::Neighbor *neighbor = NULL; 00168 00169 switch(timer->getTimerKind()){ 00170 // those timers are send by Neighbor objects 00171 case NeighborInactivityTimer: 00172 case NeighborPollTimer: 00173 case NeighborDDRetransmissionTimer: 00174 case NeighborUpdateRetransmissionTimer: 00175 case NeighborRequestRetransmissionTimer: 00176 neighbor = (AnsaOspf6::Neighbor *) msg->getContextPointer(); 00177 interface = neighbor->GetInterface(); 00178 area = interface->GetArea(); 00179 router = area->GetRouter(); 00180 00181 // those timers are send by Interface objects 00182 case InterfaceHelloTimer: 00183 case InterfaceWaitTimer: 00184 case InterfaceAcknowledgementTimer: 00185 interface = (AnsaOspf6::Interface *) msg->getContextPointer(); 00186 area = interface->GetArea(); 00187 router = area->GetRouter(); 00188 00189 // this timer is send directly by Router objects 00190 case DatabaseAgeTimer: 00191 router = (AnsaOspf6::Router *) msg->getContextPointer(); 00192 00193 default: 00194 break; 00195 } 00196 00197 // retransmit the message 00198 if (router == NULL){ 00199 ev << "OSPFv3 module received unknown timer self-message" << endl; 00200 delete msg; 00201 }else{ 00202 ev << "OSPFv3 module received known timer self-message " << endl; 00203 router->GetMessageHandler()->MessageReceived(msg); 00204 } 00205 } 00206 } 00207 00208 00209 00210 /* 00211 * Called by the NotificationBoard whenever a change of a category 00212 * occurs to which this client has subscribed. 00213 */ 00214 void AnsaOspfRouting6::receiveChangeNotification(int category, const cPolymorphic *details){ 00215 00216 if (!ospfEnabled){ 00217 return; 00218 } 00219 00220 if (simulation.getContextType()==CTX_INITIALIZE){ 00221 return; // ignore notifications during initialize 00222 } 00223 00224 Enter_Method_Silent(); 00225 printNotificationBanner(category, details); 00226 00227 if (category==NF_INTERFACE_STATE_CHANGED){ // change state of notified interface 00228 00229 InterfaceEntry *entry = check_and_cast<InterfaceEntry*>(details); 00230 00231 AnsaOspf6::Router *ospfRouter = getOspfRouter(entry->getInterfaceId()); 00232 if (ospfRouter == NULL){ 00233 return; 00234 } 00235 00236 AnsaOspf6::Interface *intf = ospfRouter->GetNonVirtualInterface(entry->getInterfaceId()); 00237 00238 if(intf != NULL){ 00239 EV << "Changing state of interface in OSPFv3\n"; 00240 if (entry->isDown()){ 00241 intf->ProcessEvent(AnsaOspf6::Interface::InterfaceDown); 00242 00243 }else{ 00244 intf->ProcessEvent(AnsaOspf6::Interface::InterfaceUp); 00245 } 00246 }else{ 00247 EV << "Not changing state of interface in OSPFv3 :(" << endl; 00248 } 00249 } 00250 } 00251 00252 00253 void AnsaOspfRouting6::addWatches(){ 00254 00255 if (ospfEnabled){ 00256 00257 WATCH_PTRMAP(routers); 00258 00259 for (int i = 0; i < ift->getNumInterfaces(); i++){ 00260 InterfaceEntry *ie = ift->getInterface(i); 00261 std::string ifaceName = ie->getName(); 00262 std::stringstream ifaceOspfProcess; 00263 00264 if (iface2Routers[i] == NULL){ 00265 ifaceOspfProcess << "OSPFv3 not running"; 00266 }else{ 00267 ifaceOspfProcess << "OSPFv3 process #"; 00268 ifaceOspfProcess << iface2Routers[i]->GetProcessID(); 00269 ifaceOspfProcess << ", router-ID: "; 00270 ifaceOspfProcess << IPAddress(iface2Routers[i]->GetRouterID()); 00271 } 00272 interfaces[ifaceName] = ifaceOspfProcess.str(); 00273 } 00274 00275 WATCH_MAP(interfaces); 00276 } 00277 } 00278 00279 AnsaOspf6::Router * AnsaOspfRouting6::getOspfRouter(int interfaceId){ 00280 InterfaceEntry *firstIface = ift->getFirstInterface(); 00281 if (firstIface == NULL){ 00282 return NULL; 00283 } 00284 00285 int dest = interfaceId - firstIface->getInterfaceId(); 00286 return iface2Routers[dest]; 00287 } 00288 00289 00290 void AnsaOspfRouting6::loadOspfRouting(cXMLElement *process){ 00291 00292 while(process != NULL){ 00293 00294 int pid; 00295 if (!xmlParser::Str2Int(&pid, process->getAttribute("id")) || pid <= 0){ 00296 throw cRuntimeError("Invalid OSPFv3 process ID"); 00297 } 00298 00299 cXMLElement *routerId = process->getFirstChildWithTag("RouterId"); 00300 if (routerId == NULL){ 00301 throw cRuntimeError("Router-ID for OSPFv3 process #%d not found", pid); 00302 } 00303 00304 IPAddress rid = routerId->getNodeValue(); 00305 00306 std::map<AnsaOspf6::ProcessID, AnsaOspf6::Router *>::iterator it; 00307 it = routers.find(pid); 00308 00309 if (it == routers.end()){ 00310 routers[pid] = new AnsaOspf6::Router(pid, rid.getInt(), this); 00311 ospfEnabled = true; 00312 }else{ 00313 routers[pid]->SetRouterID(rid.getInt()); 00314 } 00315 00316 process = xmlParser::GetOspfProcess6(process, NULL); 00317 } 00318 } 00319 00320 void AnsaOspfRouting6::loadInterfaceConfig(cXMLElement *iface){ 00321 00322 int firstIfaceId = 0; 00323 if (ift->getFirstInterface() != NULL){ 00324 firstIfaceId = ift->getFirstInterface()->getInterfaceId(); 00325 }else{ 00326 return; 00327 } 00328 00329 while (iface != NULL){ 00330 00331 InterfaceEntry *ie = ift->getInterfaceByName(iface->getAttribute("name")); 00332 if (ie == NULL){ 00333 throw cRuntimeError("Interface %s not found on this device", iface->getAttribute("name")); 00334 } 00335 00336 // let's find out if there is OSPFv3 routing enabled on this device 00337 int processId = -1; 00338 int areaId = -1; 00339 AnsaOspf6::Router *router = NULL; 00340 AnsaOspf6::Area *area = NULL; 00341 cXMLElement *processNode = iface->getFirstChildWithTag("OspfProcess6"); 00342 cXMLElement *areaNode = iface->getFirstChildWithTag("OspfArea6"); 00343 00344 if (processNode != NULL){ 00345 if (!xmlParser::Str2Int(&processId, processNode->getNodeValue()) || processId <= 0 || processId > OSPF_MAX_PROCESSID){ 00346 throw cRuntimeError("Invalid OSPFv3 process ID on interface %s", ie->getName()); 00347 } 00348 00349 std::map<AnsaOspf6::ProcessID, AnsaOspf6::Router *>::iterator it; 00350 it = routers.find(processId); 00351 if (it == routers.end()){ 00352 throw cRuntimeError("Invalid OSPFv3 process ID on interface %s (process #%d not found)", ie->getName(), processId); 00353 } 00354 00355 router = it->second; 00356 iface2Routers[ie->getInterfaceId() - firstIfaceId] = router; 00357 } 00358 00359 if (areaNode != NULL){ 00360 00361 if (router == NULL){ 00362 throw cRuntimeError("Can't load area without selecting OSPFv3 process on interface %s", ie->getName()); 00363 } 00364 00365 if (!xmlParser::Str2Int(&areaId, areaNode->getNodeValue()) || areaId < 0){ 00366 throw cRuntimeError("Invalid OSPFv3 area ID on interface %s", ie->getName()); 00367 } 00368 00369 area = router->GetArea(areaId); 00370 if (area == NULL){ 00371 area = new AnsaOspf6::Area(areaId); 00372 router->AddArea(area); 00373 } 00374 } 00375 00376 if (router != NULL && area == NULL){ 00377 throw cRuntimeError("Area ID not set on interface %s", ie->getName()); 00378 } 00379 00380 00381 // everything is fine, OSPFv3 is running 00382 if (router != NULL && area != NULL){ 00383 00384 // create interface 00385 AnsaOspf6::Interface::OspfInterfaceType type = type = AnsaOspf6::Interface::UnknownType; 00386 if (ie->isPointToPoint()){ 00387 type = AnsaOspf6::Interface::PointToPoint; 00388 }else if (ie->isBroadcast()){ 00389 type = AnsaOspf6::Interface::Broadcast; 00390 } 00391 00392 AnsaOspf6::Interface *intf = new AnsaOspf6::Interface(type); 00393 intf->SetIfIndex(ie->getInterfaceId()); 00394 intf->SetIfName(ie->getName()); 00395 intf->SetAreaID(area->GetAreaID()); 00396 intf->SetMtu(ie->getMTU()); 00397 area->AddInterface(intf); 00398 ie->setMulticast(true); 00399 00400 // load address prefixes to area 00401 cXMLElement *addr = xmlParser::GetIPv6Address(NULL, iface); 00402 while (addr != NULL){ 00403 00404 // get address string 00405 string addrFull = addr->getNodeValue(); 00406 IPv6Address ipv6; 00407 int prefixLen; 00408 00409 // check if it's a valid IPv6 address string with prefix and get prefix 00410 if (!ipv6.tryParseAddrWithPrefix(addrFull.c_str(), prefixLen)){ 00411 throw cRuntimeError("Unable to load IPv6 address prefix %s on interface %s", addrFull.c_str(), ie->getName()); 00412 } 00413 00414 ipv6 = addrFull.substr(0, addrFull.find_last_of('/')).c_str(); 00415 00416 AnsaOspf6::IPv6AddressPrefix prefix = {ipv6.getPrefix(prefixLen), prefixLen}; 00417 area->AddAddressPrefix(prefix, true); 00418 intf->AddAddressPrefix(prefix, true); 00419 00420 // get next IPv6 address 00421 addr = xmlParser::GetIPv6Address(addr, NULL); 00422 } 00423 00424 00425 // load optional parameters 00426 for (cXMLElement *param = iface->getFirstChild(); param; param = param->getNextSibling()){ 00427 00428 // instance ID 00429 if(strcmp(param->getTagName(), "OspfInstance6") == 0){ 00430 00431 int instanceId = 0; 00432 if (!xmlParser::Str2Int(&instanceId, param->getNodeValue()) || instanceId < 0 || instanceId > OSPF_MAX_INSTANCEID){ 00433 throw cRuntimeError("Invalid OSPFv3 instance ID on interface %s", ie->getName()); 00434 } 00435 00436 intf->SetInstanceID(instanceId); 00437 00438 00439 // network type 00440 }else if(strcmp(param->getTagName(), "OspfNetworkType6") == 0){ 00441 00442 const char *networkType = param->getNodeValue(); 00443 if (strcmp(networkType, "point-to-point") == 0){ 00444 intf->SetType(AnsaOspf6::Interface::PointToPoint); 00445 }else if (strcmp(networkType, "broadcast") == 0){ 00446 intf->SetType(AnsaOspf6::Interface::Broadcast); 00447 }else if (strcmp(networkType, "non-broadcast") == 0){ 00448 intf->SetType(AnsaOspf6::Interface::NBMA); 00449 }else if (strcmp(networkType, "point-to-multipoint") == 0){ 00450 intf->SetType(AnsaOspf6::Interface::PointToMultiPoint); 00451 }else{ 00452 throw cRuntimeError("Invalid network type \"%s\" on interface %s", networkType, ie->getName()); 00453 } 00454 00455 00456 // cost and priority 00457 }else if(strcmp(param->getTagName(), "OspfCost6") == 0){ 00458 00459 int cost = 0; 00460 if (!xmlParser::Str2Int(&cost, param->getNodeValue()) || cost < 1 || cost > OSPF_MAX_COST){ 00461 throw cRuntimeError("Invalid OSPFv3 cost on interface %s", ie->getName()); 00462 } 00463 00464 intf->SetOutputCost(cost); 00465 00466 }else if(strcmp(param->getTagName(), "OspfPriority6") == 0){ 00467 00468 int priority = 0; 00469 if (!xmlParser::Str2Int(&priority, param->getNodeValue()) || priority < 0 || priority > OSPF_MAX_PRIORITY){ 00470 throw cRuntimeError("Invalid OSPFv3 priority on interface %s", ie->getName()); 00471 } 00472 00473 intf->SetRouterPriority(priority); 00474 00475 00476 // timers 00477 }else if(strcmp(param->getTagName(), "OspfHelloInterval6") == 0){ 00478 00479 int timer = 0; 00480 if (!xmlParser::Str2Int(&timer, param->getNodeValue()) || timer < 1){ 00481 throw cRuntimeError("Invalid OSPFv3 hello interval on interface %s", ie->getName()); 00482 } 00483 00484 intf->SetHelloInterval(timer); 00485 00486 }else if(strcmp(param->getTagName(), "OspfRouterDeadInterval6") == 0){ 00487 00488 int timer = 0; 00489 if (!xmlParser::Str2Int(&timer, param->getNodeValue()) || timer < 1){ 00490 throw cRuntimeError("Invalid OSPFv3 dead interval on interface %s", ie->getName()); 00491 } 00492 00493 intf->SetRouterDeadInterval(timer); 00494 00495 }else if(strcmp(param->getTagName(), "OspfRetransmitInterval6") == 0){ 00496 00497 int timer = 0; 00498 if (!xmlParser::Str2Int(&timer, param->getNodeValue()) || timer < 1){ 00499 throw cRuntimeError("Invalid OSPFv3 retransmit interval on interface %s", ie->getName()); 00500 } 00501 00502 intf->SetRetransmissionInterval(timer); 00503 00504 }else if(strcmp(param->getTagName(), "OspfTransmitDelay6") == 0){ 00505 00506 int timer = 0; 00507 if (!xmlParser::Str2Int(&timer, param->getNodeValue()) || timer < 1){ 00508 throw cRuntimeError("Invalid OSPFv3 transmit delay on interface %s", ie->getName()); 00509 } 00510 00511 intf->SetTransmissionDelay(timer); 00512 } 00513 } 00514 } 00515 00516 iface = xmlParser::GetInterface(iface, NULL); 00517 } 00518 }