INET Framework for OMNeT++/OMNEST
ansaOspfRouting6.cc
Go to the documentation of this file.
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 }