--- a/src/DIF/FA/FA.cc
+++ b/src/DIF/FA/FA.cc
@@ -1,19 +1,24 @@
+// The MIT License (MIT)
//
-// Copyright Š 2014 PRISTINE Consortium (http://ict-pristine.eu)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with this program. If not, see http://www.gnu.org/licenses/.
-//
+// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
#include "FA.h"
@@ -26,276 +31,22 @@
Define_Module(FA);
FA::FA() {
- this->FaiTable = NULL;
+ N_flowTable = NULL;
}
FA::~FA() {
- this->FaiTable = NULL;
+ N_flowTable = NULL;
}
void FA::initPointers() {
- FaiTable = ModuleAccess<FAITable>(MOD_FAITABLE).get();
- Efcp = (EFCP*) ((getParentModule()->getParentModule()->getSubmodule(MOD_EFCP)->getSubmodule(MOD_EFCP)));
-
- DifAllocator = ModuleAccess<DA>(MOD_DA).get();
+ N_flowTable = check_and_cast<NFlowTable*>(getParentModule()->getSubmodule(MOD_NFLOWTABLE));
+ Efcp = check_and_cast<EFCP*>((getParentModule()->getParentModule()->getSubmodule(MOD_EFCP)->getSubmodule(MOD_EFCP)));
+
+ DifAllocator = check_and_cast<DA*>
+ (getModuleByPath("^.^.^")->getSubmodule(MOD_DIFALLOC)->getSubmodule(MOD_DA));
NFloReqPolicy = check_and_cast<NewFlowRequestBase*>(getParentModule()->getSubmodule(MOD_NEFFLOWREQPOLICY));
-}
-
-void FA::initialize() {
- initPointers();
- initSignalsAndListeners();
-
- //Setup MyAddress
- initMyAddress();
-}
-
-bool FA::changeSrcAddress(Flow* flow, bool useNeighbor) {
- //Add source...
- if (!useNeighbor) {
- flow->setSrcAddr(MyAddress);
- }
- else {
- //Ask DA which IPC to use to reach src App
- const Address* ad = DifAllocator->resolveApnToBestAddress(flow->getSrcApni().getApn(), MyAddress.getDifName());
- if (ad == NULL) {
- EV << "DifAllocator returned NULL for resolving " << flow->getSrcApni().getApn() << endl;
- return false;
- }
- Address addr = *ad;
- flow->setSrcAddr(addr);
- }
- return true;
-}
-
-bool FA::changeDstAddresses(Flow* flow, bool useNeighbor) {
- //Ask DA which IPC to use to reach dst App
- const Address* ad = DifAllocator->resolveApnToBestAddress(flow->getDstApni().getApn());
- if (ad == NULL) {
- EV << "DifAllocator returned NULL for resolving " << flow->getDstApni().getApn() << endl;
- return false;
- }
- Address addr = *ad;
-
- //...and destination addresses
-
- //If destination address does have neighbor then use first neighbor address
- if (useNeighbor) {
- const APNList* apnlist = DifAllocator->findApnNeigbors(addr.getIpcAddress());
- if (apnlist)
- addr.setIpcAddress(apnlist->front());
- }
-
- flow->setDstAddr(addr);
-
- return true;
-}
-
-bool FA::receiveAllocateRequest(Flow* flow) {
- Enter_Method("receiveAllocateRequest()");
- EV << this->getFullPath() << " received AllocateRequest" << endl;
-
- //Insert new Flow into FAITable
- FaiTable->insertNew(flow);
-
- //Change allocation status to pending
- FaiTable->changeAllocStatus(flow, FAITableEntry::ALLOC_PEND);
-
- //Add source and destination address
- setOriginalAddresses(flow);
- setNeighborAddresses(flow);
-
- //Is malformed?
- if (isMalformedFlow(flow)){
- FaiTable->changeAllocStatus(flow, FAITableEntry::ALLOC_ERR);
- //TODO: Vesely - What about special signal for errors????
- //this->signalizeAllocateResponseNegative(fl);
- return false;
- }
-
- //Create FAI
- FAI* fai = this->createFAI(flow);
-
- //Update flow object
- flow->setSrcPortId(fai->getLocalPortId());
- flow->getConnectionId().setSrcCepId(fai->getLocalCepId());
-
- //Are both Apps local? YES then Degenerate transfer
- if ( DifAllocator->isAppLocal( flow->getDstApni().getApn() ) ) {
- fai->setDegenerateDataTransfer(true);
- flow->setDdtFlag(true);
- }
- bool status;
- status = fai->receiveAllocateRequest();
- //Potentially wait for response from RA, after this continue with X
-
- return status;
-}
-
-bool FA::receiveCreateFlowRequestFromRibd(Flow* flow) {
- Enter_Method("receiveCreateFlowRequest()");
- EV << this->getFullPath() << " received CreateFlowRequest" << endl;
-
- bool status;
-
- //Is requested APP local?
- if ( DifAllocator->isAppLocal(flow->getSrcApni().getApn()) ){
- //Check for duplicity
- if (!DifAllocator->isAppLocal(flow->getDstApni().getApn())
- && FaiTable->findEntryByInvokeId(flow->getAllocInvokeId())
- ) {
- EV << "Duplicit M_CREATE received thus ignoring!" << endl;
- return false;
- }
-
- //Insert new Flow into FAITable
- FaiTable->insertNew(flow);
- //Change neighbor addresses
- setNeighborAddresses(flow);
- EV << "Processing M_CREATE(flow)" << endl;
- //Change allocation status to pending
- FaiTable->changeAllocStatus(flow, FAITableEntry::ALLOC_PEND);
-
- //Create FAI
- FAI* fai = this->createFAI(flow);
- if ( DifAllocator->isAppLocal( flow->getDstApni().getApn() ) ) {
- fai->setDegenerateDataTransfer(true);
- flow->setDdtFlag(true);
- }
- fai->setRemotePortId(flow->getDstPortId());
- fai->setRemoteCepId(flow->getConId().getDstCepId());
-
- //Update flow object
- flow->setSrcPortId(fai->getLocalPortId());
- flow->getConnectionId().setSrcCepId(fai->getLocalCepId());
-
- //Pass the CreateRequest to newly created FAI
- status = fai->receiveCreateRequest();
-
- }
- //...if not then forward CreateRequest Flow to next neighbor
- else {
- EV << "Forwarding M_CREATE(flow)" << endl;
-
- //Before that reverse SRC-DST information back
- flow->swapFlow();
- //Insert new Flow into FAITable
- FaiTable->insertNew(flow);
- //Change neighbor addresses
- setNeighborAddresses(flow);
- //Change status to forward
- FaiTable->changeAllocStatus(flow, FAITableEntry::FORWARDING);
-
- //Decrement HopCount
- flow->setHopCount(flow->getHopCount() - 1);
- if (!flow->getHopCount()) {
- //TODO: Vesely - More granular error
- FaiTable->changeAllocStatus(flow, FAITableEntry::ALLOC_ERR);
- //Schedule M_Create_R(Flow)
- this->signalizeCreateFlowResponseNegative(flow);
- return false;
- }
-
- // bind this flow to a suitable (N-1)-flow
- RABase* raModule = (RABase*) getModuleByPath("^.^.resourceAllocator.ra");
- status = raModule->bindNFlowToNM1Flow(flow);
-
- //EV << "status: " << status << endl;
- if (status == true) {
- // flow is already allocated
- receiveNM1FlowCreated(flow);
- }
- //else WAIT until allocation of N-1 flow is completed
- else {
- EV << "FA waits until N-1 IPC allocates auxilliary N-1 flow" << endl;
- }
- }
- return status;
-}
-
-bool FA::receiveDeallocateRequest(Flow* flow) {
- Enter_Method("receiveDeallocateRequest()");
- EV << this->getFullPath() << " received DeallocateRequest" << endl;
-
- //Check flow in table
- FAITableEntry* fte = FaiTable->findEntryByFlow(flow);
- if (fte && fte->getFai()) {
- //Pass the request to appropriate FAI
- FAIBase* fai = fte->getFai();
- FaiTable->changeAllocStatus(fai, FAITableEntry::DEALLOC_PEND);
-
- fai->receiveDeallocateRequest();
- return true;
- }
- else {
- if (!fte)
- EV << "Flow or FAI not found in FAITable!" << endl;
- else if (fte->getAllocateStatus() != FAITableEntry::TRANSFER)
- EV << "Cannot deallocate flow which is not in tranfer phase!" << endl;
- return false;
- }
-}
-
-bool FA::invokeNewFlowRequestPolicy(Flow* flow) {
- return NFloReqPolicy->run(*flow);
-}
-
-FAI* FA::createFAI(Flow* flow) {
- // find factory object
- cModuleType *moduleType = cModuleType::get("rina.DIF.FA.FAI");
-
- //Prepare parameters
- int portId = ev.getRNG(RANDOM_NUMBER_GENERATOR)->intRand(MAX_PORTID);
- int cepId = ev.getRNG(RANDOM_NUMBER_GENERATOR)->intRand(MAX_CEPID);
-
- //Create a name
- std::ostringstream ostr;
- ostr << "fai_" << portId << "_" << cepId;
-
- //Instantiate module
- cModule *module = moduleType->create(ostr.str().c_str(), this->getParentModule());
- module->par(PAR_LOCALPORTID) = portId;
- module->par(PAR_LOCALCEPID) = cepId;
- module->par(PAR_CREREQTIMEOUT) = par(PAR_CREREQTIMEOUT).doubleValue();
- module->finalizeParameters();
- module->buildInside();
-
- // create activation message
- module->scheduleStart(simTime());
- module->callInitialize();
-
- //Prepare return pointer and setup internal FAI pointers
- FAI* fai = dynamic_cast<FAI*>(module);
- fai->postInitialize(this, flow, Efcp);
-
- //Change state in FAITable
- FaiTable->setFaiToFlow(fai, flow);
- FaiTable->changeAllocStatus(flow, FAITableEntry::ALLOC_PEND);
-
- return fai;
-}
-
-void FA::deinstantiateFai(Flow* flow) {
- FaiTable->changeAllocStatus(flow, FAITableEntry::DEINSTANTIATED);
- //TODO: Vesely
- //Prepare deinstantitation self-message
-}
-
-void FA::handleMessage(cMessage *msg) {
- //Rcv Allocate_Request
-
- //Rcv M_Create(Flow)
-
- //Rcv Deallocate_Request
-
- //Deinstantiation
- //deleteModule();
-}
-
-bool FA::isMalformedFlow(Flow* flow) {
- //TODO: Vesely - Simulate malformed
- if ( !strcmp(flow->getDstApni().getApn().getName().c_str(), "AppERR") )
- return true;
- return false;
+ RaModule = check_and_cast<RABase*>( getModuleByPath("^.^.resourceAllocator.ra") );
+ Enrollment = check_and_cast<EnrollmentStateTable*>( getModuleByPath("^.^.enrollment.enrollmentStateTable") );
}
void FA::initSignalsAndListeners() {
@@ -306,6 +57,7 @@
sigFACreReqFwd = registerSignal(SIG_FA_CreateFlowRequestForward);
sigFACreResPosiFwd = registerSignal(SIG_FA_CreateFlowResponseForward);
sigFACreResNega = registerSignal(SIG_FA_CreateFlowResponseNegative);
+ sigFAAllocFinMgmt = registerSignal(SIG_FA_MgmtFlowAllocated);
//Signals that this module is processing
// AllocateRequest
@@ -323,63 +75,37 @@
lisCreReq = new LisFACreReq(this);
catcher2->subscribe(SIG_RIBD_CreateRequestFlow, lisCreReq);
-}
-
-void FA::signalizeCreateFlowRequestForward(Flow* flow) {
- emit(this->sigFACreReqFwd, flow);
-}
-
-void FA::receiveNM1FlowCreated(Flow* flow) {
- Enter_Method("receiveNM1FlowCreated()");
- EV << "Continue M_CREATE(flow) forward!" << endl;
-
- Flow* tmpfl = flow->dup();
- FaiTable->changeAllocStatus(flow, FAITableEntry::FORWARDED);
- setNeighborAddresses(tmpfl);
-
- this->signalizeCreateFlowRequestForward(tmpfl);
-}
-
-void FA::signalizeCreateFlowResponseNegative(Flow* flow) {
- emit(this->sigFACreResNega, flow);
-}
-
-bool FA::setOriginalAddresses(Flow* flow) {
- Address adr = getAddressFromDa(flow->getSrcApni().getApn(), false);
- if (adr.isUnspecified())
- return false;
- flow->setSrcAddr(adr);
-
- adr = getAddressFromDa(flow->getDstApni().getApn(), false);
- if (adr.isUnspecified())
- return false;
- flow->setDstAddr(adr);
- return true;
-}
-
-bool FA::setNeighborAddresses(Flow* flow) {
- Address adr = getAddressFromDa(flow->getSrcApni().getApn(), true);
- if (adr.isUnspecified())
- return false;
- flow->setSrcNeighbor(adr);
-
- adr = getAddressFromDa(flow->getDstApni().getApn(), true);
- if (adr.isUnspecified())
- return false;
- flow->setDstNeighbor(adr);
- return true;
-}
-
-const Address FA::getAddressFromDa(const APN& apn, bool useNeighbor) {
- //Ask DA which IPC to use to reach src App
- const Address* ad = DifAllocator->resolveApnToBestAddress(apn, MyAddress.getDifName());
- if (ad == NULL) {
- EV << "DifAllocator returned NULL for resolving " << apn << endl;
- return Address();
- }
- Address addr = *ad;
+ //Allocate after management flow is prepared (enrollment done)
+ lisEnrollFin = new LisFAAllocFinMgmt(this);
+ //catcher2->subscribe(SIG_FAI_AllocateFinishManagement, lisAllocFinMgmt);
+ catcher2->subscribe(SIG_ENROLLMENT_Finished, lisEnrollFin);
+
+}
+
+void FA::initialize() {
+ initPointers();
+ initSignalsAndListeners();
+
+ //Setup MyAddress
+ initMyAddress();
+}
+//XXX: Vesely - Dirty! Needs refactoring...
+const Address FA::getAddressFromDa(const APN& apn, bool useNeighbor, bool isMgmtFlow) {
+ Address addr;
+ if (!isMgmtFlow) {
+ //Ask DA which IPC to use to reach src App
+ const Address* ad = DifAllocator->resolveApnToBestAddress(apn, MyAddress.getDifName());
+ if (ad == NULL) {
+ EV << "DifAllocator returned NULL for resolving " << apn << endl;
+ return Address();
+ }
+ addr = *ad;
+ }
+ else {
+ addr = Address(apn);
+ }
if (useNeighbor) {
- const APNList* apnlist = DifAllocator->findApnNeigbors(addr.getApname());
+ const APNList* apnlist = DifAllocator->findApnNeigbors(addr.getApn());
if (apnlist) {
for (ApnCItem it = apnlist->begin(); it != apnlist->end(); ++it) {
Address tmp = Address(it->getName());
@@ -393,3 +119,398 @@
}
return addr;
}
+bool FA::isMalformedFlow(Flow* flow) {
+ //TODO: Vesely - Simulate malformed
+ if ( !strcmp(flow->getDstApni().getApn().getName().c_str(), "AppERR") )
+ return true;
+ return false;
+}
+
+void FA::handleMessage(cMessage *msg) {
+ if ( msg->isSelfMessage() && !opp_strcmp(msg->getName(), TIM_FAPENDFLOWS) ) {
+ while (!PendingFlows.empty()) {
+ NFlowTableEntry* fte = N_flowTable->findEntryByFlow(PendingFlows.front());
+ if (fte && fte->getFai()) {
+ FAIBase* fai = fte->getFai();
+ if (fai) {
+ fai->receiveAllocateRequest();
+ }
+ }
+ PendingFlows.pop_front();
+ }
+ cancelAndDelete(msg);
+ }
+ else
+ {
+ EV << "Unsupported message received by FA " << getFullName() << endl;
+ }
+}
+
+bool FA::changeSrcAddress(Flow* flow, bool useNeighbor) {
+ //Add source...
+ if (!useNeighbor) {
+ flow->setSrcAddr(MyAddress);
+ }
+ else {
+ //Ask DA which IPC to use to reach src App
+ const Address* ad = DifAllocator->resolveApnToBestAddress(flow->getSrcApni().getApn(), MyAddress.getDifName());
+ if (ad == NULL) {
+ EV << "DifAllocator returned NULL for resolving " << flow->getSrcApni().getApn() << endl;
+ return false;
+ }
+ Address addr = *ad;
+ flow->setSrcAddr(addr);
+ }
+ return true;
+}
+
+bool FA::changeDstAddresses(Flow* flow, bool useNeighbor) {
+ //Ask DA which IPC to use to reach dst App
+ const Address* ad = DifAllocator->resolveApnToBestAddress(flow->getDstApni().getApn());
+ if (ad == NULL) {
+ EV << "DifAllocator returned NULL for resolving " << flow->getDstApni().getApn() << endl;
+ return false;
+ }
+ Address addr = *ad;
+
+ //...and destination addresses
+
+ //If destination address does have neighbor then use first neighbor address
+ if (useNeighbor) {
+ const APNList* apnlist = DifAllocator->findApnNeigbors(addr.getIpcAddress());
+ if (apnlist)
+ addr.setIpcAddress(apnlist->front());
+ }
+
+ flow->setDstAddr(addr);
+
+ return true;
+}
+
+//XXX: Vesely - Dirty! Needs refactoring...
+bool FA::setOriginalAddresses(Flow* flow) {
+ Address adr = getAddressFromDa(flow->getSrcApni().getApn(), false, false);
+ if (adr.isUnspecified())
+ return false;
+ flow->setSrcAddr(adr);
+
+ adr = getAddressFromDa(flow->getDstApni().getApn(), false, false);
+ if (adr.isUnspecified())
+ return false;
+ flow->setDstAddr(adr);
+ return true;
+}
+//XXX: Vesely - Dirty! Needs refactoring...
+bool FA::setNeighborAddresses(Flow* flow) {
+ Address adr;
+ if (!flow->isManagementFlowLocalToIPCP()) {
+ adr = getAddressFromDa(flow->getSrcApni().getApn(), true, flow->isManagementFlowLocalToIPCP());
+ if (adr.isUnspecified())
+ return false;
+ flow->setSrcNeighbor(adr);
+ }
+
+ adr = getAddressFromDa(flow->getDstApni().getApn(), true, flow->isManagementFlowLocalToIPCP());
+ if (adr.isUnspecified())
+ return false;
+ flow->setDstNeighbor(adr);
+ return true;
+}
+
+bool FA::receiveAllocateRequest(Flow* flow) {
+ Enter_Method("receiveAllocateRequest()");
+ EV << this->getFullPath() << " received AllocateRequest" << endl;
+
+ //Insert new Flow into FAITable
+ N_flowTable->insertNew(flow);
+
+ //Change allocation status to pending
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_PEND);
+
+ //Add source and destination address in case of data flow
+ if (flow->getSrcAddr() == Address::UNSPECIFIED_ADDRESS
+ && flow->getSrcNeighbor() == Address::UNSPECIFIED_ADDRESS) {
+ setOriginalAddresses(flow);
+ setNeighborAddresses(flow);
+ //XXX: Vesely - Dirty! Needs refactoring...
+ flow->setSrcNeighbor(flow->getSrcAddr());
+ }
+
+ //Are both Apps local? YES then Degenerate transfer
+ if ( DifAllocator->isAppLocal( flow->getDstApni().getApn() ) ) {
+ flow->setDdtFlag(true);
+ }
+
+ //Check whether local IPCP is enrolled into DIF
+ //Successful enrollment implies existence of N-1 mgmt-flow, if not then
+ //FA needs to init allocation of N-1 mgmt-flow
+ if (!flow->isDdtFlag() && !Enrollment->isEnrolled(MyAddress.getApn())) {
+ EV << "IPCP not enrolled to DIF, thus executing enrollment!" << endl;
+ receiveMgmtAllocateRequest(APNamingInfo(MyAddress.getApn()), APNamingInfo(flow->getDstNeighbor().getApn()));
+ }
+
+ //Is malformed?
+ if (isMalformedFlow(flow)){
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_ERR);
+ //TODO: Vesely - What about special signal for errors????
+ //this->signalizeAllocateResponseNegative(fl);
+ return false;
+ }
+
+ //Create FAI
+ FAI* fai = this->createFAI(flow);
+ fai->setDegenerateDataTransfer(flow->isDdtFlag());
+
+ //Update flow object
+ flow->setSrcPortId(fai->getLocalPortId());
+ flow->getConnectionId().setSrcCepId(fai->getLocalCepId());
+
+ //Postpone allocation request until management flow is ready
+ bool status;
+ if ( flow->isDdtFlag() || Enrollment->isEnrolled(MyAddress.getApn())
+ ){
+ status = fai->receiveAllocateRequest();
+ }
+ else
+ {
+ status = true;
+ EV << "Management flow is not ready!" << endl;
+ }
+
+ //Potentially wait for response from RA, after this continue with X
+
+ return status;
+}
+
+bool FA::receiveMgmtAllocateRequest(Flow* mgmtflow) {
+ bool status = true;
+ //If N-1 mgmt-flow not ready, then allocate
+ if (!RaModule->hasFlow(mgmtflow->getDstAddr().getApn().getName(), VAL_MGMTQOSID)) {
+ status = RaModule->bindNFlowToNM1Flow(mgmtflow);
+ }
+
+ //If N-1 mgmt ready, then starting enrollment procedure
+ APNIPair* apnip = new APNIPair(mgmtflow->getSrcApni(), mgmtflow->getDstApni());
+ if (status) {
+ emit(sigFAAllocFinMgmt, apnip);
+ }
+
+ return status;
+}
+
+bool FA::receiveMgmtAllocateRequest(APNamingInfo src, APNamingInfo dst) {
+ Enter_Method("receiveLocalMgmtAllocateRequest()");
+ EV << this->getFullPath() << " received LocalMgmtAllocateRequest" << endl;
+
+ Flow* mgmtflow = new Flow(src, dst);
+ mgmtflow->setQosRequirements(QoSReq::MANAGEMENT);
+ mgmtflow->setSrcAddr(Address(src.getApn()));
+ mgmtflow->setDstAddr(Address(dst.getApn()));
+ mgmtflow->setSrcNeighbor(Address(src.getApn()));
+ mgmtflow->setDstNeighbor(Address(dst.getApn()));
+
+ bool status = true;
+ //If N-1 mgmt-flow not ready, then allocate
+ if (!RaModule->hasFlow(mgmtflow->getDstAddr().getApn().getName(), VAL_MGMTQOSID)) {
+ status = RaModule->bindNFlowToNM1Flow(mgmtflow);
+ }
+
+ //If N-1 mgmt ready, then starting enrollment procedure
+ APNIPair* apnip = new APNIPair(mgmtflow->getSrcApni(), mgmtflow->getDstApni());
+ if (status) {
+ emit(sigFAAllocFinMgmt, apnip);
+ }
+
+ return status;
+}
+
+bool FA::receiveMgmtAllocateFinish() {
+ Enter_Method("receiveAllocFinishMgmt()");
+ scheduleAt(simTime(), new cMessage(TIM_FAPENDFLOWS) );
+ //TODO: Vesely - Fix unused return value
+ return true;
+}
+
+bool FA::receiveCreateFlowRequestFromRibd(Flow* flow) {
+ Enter_Method("receiveCreateFlowRequest()");
+ EV << this->getFullPath() << " received CreateFlowRequest" << endl;
+
+ bool status;
+
+ //Is requested APP local?
+ if ( DifAllocator->isAppLocal(flow->getSrcApni().getApn()) ){
+ //Check for duplicity
+ if (!DifAllocator->isAppLocal(flow->getDstApni().getApn())
+ && N_flowTable->findEntryByInvokeId(flow->getAllocInvokeId())
+ ) {
+ EV << "Duplicit M_CREATE received thus ignoring!" << endl;
+ return false;
+ }
+
+ //Insert new Flow into FAITable
+ N_flowTable->insertNew(flow);
+
+ //Change neighbor addresses
+ //if (!flow->isManagementFlowLocalToIPCP()) {
+ setNeighborAddresses(flow);
+ //XXX: Vesely - Dirty! Needs refactoring...
+ flow->setSrcNeighbor(flow->getSrcAddr());
+ //}
+
+ EV << "Processing M_CREATE(flow)" << endl;
+ //Change allocation status to pending
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_PEND);
+
+ //Create FAI
+ FAI* fai = this->createFAI(flow);
+ if ( DifAllocator->isAppLocal( flow->getDstApni().getApn() ) ) {
+ fai->setDegenerateDataTransfer(true);
+ flow->setDdtFlag(true);
+ }
+ fai->setRemotePortId(flow->getDstPortId());
+ fai->setRemoteCepId(flow->getConId().getDstCepId());
+
+ //Update flow object
+ flow->setSrcPortId(fai->getLocalPortId());
+ flow->getConnectionId().setSrcCepId(fai->getLocalCepId());
+
+ //Pass the CreateRequest to newly created FAI
+ status = fai->receiveCreateRequest();
+
+ }
+ //...if not then forward CreateRequest Flow to next neighbor
+ else {
+ EV << "Forwarding M_CREATE(flow)" << endl;
+
+ //Before that reverse SRC-DST information back
+ flow->swapFlow();
+ //Insert new Flow into FAITable
+ N_flowTable->insertNew(flow);
+ //Change neighbor addresses
+ setNeighborAddresses(flow);
+ //Change status to forward
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::FORWARDING);
+
+ //Decrement HopCount
+ flow->setHopCount(flow->getHopCount() - 1);
+ if (!flow->getHopCount()) {
+ //TODO: Vesely - More granular error
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_ERR);
+ //Schedule M_Create_R(Flow)
+ this->signalizeCreateFlowResponseNegative(flow);
+ return false;
+ }
+
+ // bind this flow to a suitable (N-1)-flow
+ RABase* raModule = (RABase*) getModuleByPath("^.^.resourceAllocator.ra");
+ status = raModule->bindNFlowToNM1Flow(flow);
+
+ //EV << "status: " << status << endl;
+ if (status == true) {
+ // flow is already allocated
+ receiveNM1FlowCreated(flow);
+ }
+ //else WAIT until allocation of N-1 flow is completed
+ else {
+ EV << "FA waits until N-1 IPC allocates auxilliary N-1 flow" << endl;
+ }
+ }
+ return status;
+}
+
+bool FA::receiveDeallocateRequest(Flow* flow) {
+ Enter_Method("receiveDeallocateRequest()");
+ EV << this->getFullPath() << " received DeallocateRequest" << endl;
+
+ //Check flow in table
+ NFlowTableEntry* fte = N_flowTable->findEntryByFlow(flow);
+ if (fte && fte->getFai()) {
+ //Pass the request to appropriate FAI
+ FAIBase* fai = fte->getFai();
+ N_flowTable->changeAllocStatus(fai, NFlowTableEntry::DEALLOC_PEND);
+
+ fai->receiveDeallocateRequest();
+ return true;
+ }
+ else {
+ if (!fte)
+ EV << "Flow or FAI not found in FAITable!" << endl;
+ else if (fte->getAllocateStatus() != NFlowTableEntry::TRANSFER)
+ EV << "Cannot deallocate flow which is not in tranfer phase!" << endl;
+ return false;
+ }
+}
+
+void FA::receiveNM1FlowCreated(Flow* flow) {
+ Enter_Method("receiveNM1FlowCreated()");
+ EV << "Continue M_CREATE(flow) forward!" << endl;
+
+ Flow* tmpfl = flow->dup();
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::FORWARDED);
+ setNeighborAddresses(tmpfl);
+
+ this->signalizeCreateFlowRequestForward(tmpfl);
+}
+
+bool FA::invokeNewFlowRequestPolicy(Flow* flow) {
+ return NFloReqPolicy->run(*flow);
+}
+
+FAI* FA::createFAI(Flow* flow) {
+ //@Vladimir: what about using ExternConsts.cc for this?
+ // find factory object
+ cModuleType *moduleType = cModuleType::get("rina.src.DIF.FA.FAI");
+
+ //Prepare parameters
+ int portId = ev.getRNG(RANDOM_NUMBER_GENERATOR)->intRand(MAX_PORTID);
+ int cepId = ev.getRNG(RANDOM_NUMBER_GENERATOR)->intRand(MAX_CEPID);
+
+ //Create a name
+ std::ostringstream ostr;
+ ostr << "fai_" << portId << "_" << cepId;
+
+ //Instantiate module
+ cModule *module = moduleType->create(ostr.str().c_str(), this->getParentModule());
+ module->par(PAR_LOCALPORTID) = portId;
+ module->par(PAR_LOCALCEPID) = cepId;
+ //module->par(PAR_CREREQTIMEOUT) = par(PAR_CREREQTIMEOUT).doubleValue();
+ module->finalizeParameters();
+ module->buildInside();
+
+ // create activation message
+ module->scheduleStart(simTime());
+ module->callInitialize();
+
+ //Layouting
+ /*
+ module->getDisplayString().setTagArg("p", 0, "100");
+ std::ostringstream os;
+ os << (70 + N_flowTable->getSize() * 50);
+ module->getDisplayString().setTagArg("p", 1, os.str().c_str());
+ */
+
+ //Prepare return pointer and setup internal FAI pointers
+ FAI* fai = dynamic_cast<FAI*>(module);
+ fai->postInitialize(this, flow, Efcp);
+
+ //Change state in FAITable
+ N_flowTable->setFaiToFlow(fai, flow);
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_PEND);
+
+ return fai;
+}
+
+void FA::deinstantiateFai(Flow* flow) {
+ N_flowTable->changeAllocStatus(flow, NFlowTableEntry::DEINSTANTIATED);
+ //TODO: Vesely
+ //Prepare deinstantitation self-message
+}
+
+void FA::signalizeCreateFlowRequestForward(Flow* flow) {
+ emit(this->sigFACreReqFwd, flow);
+}
+
+void FA::signalizeCreateFlowResponseNegative(Flow* flow) {
+ emit(this->sigFACreResNega, flow);
+}
+