00001 00002 // PROYECTO FIN DE CARRERA // 00003 // TITULO: Disenyo de nuevas arquitecturas y algoritmos de gestión de recursos en // 00004 // redes de acceso FiWi // 00005 // AUTOR: Ana Emma Lopez Mato // 00006 // TUTOR: Noemi Merayo Alvarez // 00007 // INGENIERIA TECNICA DE TELECOMUNICACIONES, SISTEMAS DE TELECOMUNICACION // 00008 // UNIVERSIDAD DE VALLADOLID // 00010 00011 #include "ONU_WDMSplitter.h" 00012 #include "GATE_m.h" 00013 #include "REPORT_m.h" 00014 #include "ETHERNET_m.h" 00015 #include <vector> 00016 #include "analysis.h" 00017 #include <string.h> 00018 #include <stdio.h> 00019 #include "ONU_Table.h" 00020 /* 00021 * MODULO ONU_WDMSplitter: 00022 */ 00023 Define_Module(ONU_WDMSplitter); 00024 00026 //FUNCION INITIALIZE()--> ESTA FUNCION SE INVOCA DESPUES DE QUE OMNET++ HA PUESTO EN MARCHA LA RED, EN LA CUAL SE LEEN LOS // 00027 // PARAMETROS DEL MODULO Y SE INICIALIZAN TODAS DAS LAS VARIABLES DECLARADAS PARA ESTE MODULO SIMPLE, SE // 00028 // ASIGNAN ESTRUCTURAS DE DATOS DINAMICOS Y SE ASIGNAN E INICIALIZAN LOS AUTOMENSAJES SI SON NECESARIOS // 00029 // PARA EL FUNCIONAMIENTO DE ESTE MODULO. // 00031 void ONU_WDMSplitter::initialize() 00032 { 00033 // RECOGIDA DE ESTADISTICAS DE TIEMPO ENTRE CICLOS MANUALMENTE 00034 time_cycles.setName("Tiempo entre ciclos"); 00035 00036 // INICIALIZAMOS VARIABLES AL VALOR 0 00037 timepacketethernet = 0; // TIEMPO EN EL QUE SE ENVIARA EL PAQUETE ETHERNET 00038 time_report = 0; // TIEMPO EN EL QUE SE ENVIA EL PAQUETE REPORT 00039 time_gate = 0; // TIEMPO EN EL QUE LLEGA EL PAQUETE GATE A LA ONU 00040 lambda = 0; 00041 onu = 0 ; 00042 tampacketextract = 0; 00043 bw_perdido=0; 00044 sent_messages = 0; 00045 // CODIGO PARA MODIFICAR EL DELAY DEL CANAL QUE UNE EL SPLITTER Y LAS ONUS 00046 if((int)par("methodlength_longvariable0_longfija1")==0) 00047 { 00048 cTopology topo; // DEFINIMOS UN PARAMETRO DE LA TOPOLOGIA DE LA RED 00049 topo.extractByParameter( "numlong" ); // EXTRAEMOS LOS NODOS DE NUESTRA RED QUE UTILIZAN EL PARAMETRO numlong 00050 // PARA VISUALIZAR LOS NODOS DE LA TOPOLOGAA Y SUS CONEXIONES 00051 //for (int i=0; i<topo.getNumNodes(); i++) 00052 //{ 00053 // cTopology::Node *node = topo.getNode(i); 00054 // //ev<<"Node i=" << i << " is " << node->getModule()->getFullPath() << endl; 00055 // //ev<<" It has " << node->getNumOutLinks() << " conns to other nodes\n"; 00056 // //ev<<" and " << node->getNumInLinks() << " conns from other nodes\n"; 00057 00058 // //ev<<" Connections to other modules are:\n"; 00059 // for (int j=0; j<node->getNumOutLinks(); j++) 00060 // { 00061 // cTopology::Node *neighbour = node->getLinkOut(j)->getRemoteNode(); 00062 // cGate *gate = node->getLinkOut(j)->getLocalGate(); 00063 // //ev<<" " << neighbour->getModule()->getFullPath() 00064 // << " through gate " << gate->getFullName() << endl; 00065 // } 00066 00067 // } 00068 00069 // DEFINIMOS EL PARAMETRO MODULE QUE NOS INDICA EL CAMINO HASTA EL NODO DEL QUE QUEREMOS OBTENER INFORMACION 00070 cModule *module = getParentModule()->getParentModule()->getSubmodule("onu", getParentModule()->getIndex()); 00071 double delay = intuniform(0,10)*1000*0.000000005; // CALCULAMOS EL RETARDO DEL SEGMENTO QUE UNA EL SPLITTER CON LA ONU MEDIANTE DISTANCIAS ALEATORIAS ENTE 0 Y 10 KM 00072 00073 cTopology::Node *nodeonuOut = topo.getNodeFor(module); // NOMBRE DEL NODO QUE SACAMOS DEL GRAFO 00074 // RECORREMOS CON EL BUCLE FOR TODOS LOS ENLACES DE SALIDA QUE TIENE ESE NODO PARA OBTENER LA INFORMACION QUE SOLICITAMOS 00075 for(int j=0; j<nodeonuOut->getNumOutLinks(); j++) 00076 { 00077 // OBTENEMOS EL VALOR DEL RETARDO QUE HAY EN EL CANAL QUE PASA POR EL NODO EN EL QUE OBTENEMOS LA INFORMACION Y LO VISUALIZAMOS POR PANTALLA 00078 SIMTIME_DBL((check_and_cast<cDelayChannel*>(nodeonuOut->getLinkOut(j)->getLocalGate()->getChannel()))->getDelay()); 00079 ev<<" Delay del canal descendente antes de Inicializar: "<<SIMTIME_DBL((check_and_cast<cDelayChannel*>(nodeonuOut->getLinkOut(j)->getLocalGate()->getChannel()))->getDelay())<<endl; 00080 00081 // INTRODUCIMOS EL NUEVO VALOR DEL RETARDO DEL CANAL Y LO VISUALIZAMOS POR PANTALLA 00082 (check_and_cast<cDelayChannel*>(nodeonuOut->getLinkOut(j)->getLocalGate()->getChannel()))->setDelay(delay); 00083 ev<<" Nuevo Delay del canal descendente: "<<(check_and_cast<cDelayChannel*>(nodeonuOut->getLinkOut(j)->getLocalGate()->getChannel()))->getDelay()<<endl; 00084 } 00085 00086 cTopology::Node *nodeonuIn = topo.getNodeFor(module); // NOMBRE DEL NODO QUE SACAMOS DEL GRAFO 00087 // RECORREMOS CON EL BUCLE FOR TODOS LOS ENLACES DE ENTRADA QUE TIENE ESE NODO PARA OBTENER LA INFORMACION QUE SOLICITAMOS 00088 for(int j=0; j<nodeonuIn->getNumInLinks(); j++) 00089 { 00090 // OBTENEMOS EL VALOR DEL RETARDO QUE HAY EN EL CANAL QUE PASA POR EL NODO EN EL QUE OBTENEMOS LA INFORMACION Y LO VISUALIZAMOS POR PANTALLA 00091 SIMTIME_DBL((check_and_cast<cDelayChannel*>(nodeonuIn->getLinkIn(j)->getRemoteGate()->getChannel()))->getDelay()); 00092 ev<<" Delay del canal ascendente antes de Inicializar: "<<SIMTIME_DBL((check_and_cast<cDelayChannel*>(nodeonuIn->getLinkIn(j)->getRemoteGate()->getChannel()))->getDelay())<<endl; 00093 00094 // INTRODUCIMOS EL NUEVO VALOR DEL RETARDO DEL CANAL Y LO VISUALIZAMOS POR PANTALLA 00095 (check_and_cast<cDelayChannel*>(nodeonuIn->getLinkIn(j)->getRemoteGate()->getChannel()))->setDelay(delay); 00096 ev<<" Nuevo Delay del canal ascendente: "<<(check_and_cast<cDelayChannel*>(nodeonuIn->getLinkIn(j)->getRemoteGate()->getChannel()))->getDelay()<<endl; 00097 } 00098 } 00100 // DEFININOS EL PROCESO PARA PODER ENTRAR DESDE ESTE MODULO AL MODULO ONU_TABLE 00101 cModule *c_onutable_module; 00102 00103 00104 c_onutable_module = getParentModule()->getSubmodule("onu_table"); // CAMINO PARA LLEGAR HASTA EL MODULO ONU_TABLE 00105 table_module = check_and_cast<ONU_Table *>(c_onutable_module); // ENTRAMOS Y CHEQUEAMOS EL MODULO ONU_TABLE 00106 00107 00108 } 00109 00111 //FUNCION HANDLEMESSAGE(CMESSAGE *)--> ESTA FUNCION SE INVOCA CON EL MENSAJE COMO PARAMETRO CADA VEZ QUE EL MODULO RECIBE UN // 00112 // UN MENSAJE O PAQUETE. SE RECORRE EL CODIGO IMPLEMENTADO PARA DEVOLVER UN VALOR O // 00113 // EJECUTAR UNA FUNCION DENTRO DEL MODULO SIMPLE. EL TIEMPO DE SIMULACION NO TRANSCURRE // 00114 // DENTRO DE LA LLAMADA DE LA FUNCION HANDLEMESSAGE(CMESSAGE *MSG) MIENTRAS RECORRE EL // 00115 // CODIGO IMPLEMENTADO. // // 00117 void ONU_WDMSplitter::handleMessage(cMessage *msg) 00118 { 00119 // VARIABLES 00120 simtime_t comprobar_tiempo_ciclos; // VARIABLE QUE INDICA EL TIEMPO QUE SE PIERDE ENTRE EL FINAL Y EL PRINCIPIO DE UN CICLO 00121 int type = msg->getKind(); // VARIABLE TYPE PARA IDENTIFICAR LOS MENSAJES DE LA RED 00122 double txrate = (int)par("txrate"); // TASA DE TRANSMISION EN BITS POR SEGUNDO 00123 int p= gateSize("wdmnet"); // TAMA�O DE LA PUERTA wdmnet DEL MODULO ONU_WDMSPLITTER 00124 00125 // ESTRUCTURA CONDICIONAL SWITCH QUE NOS DIFERENCIA LOS MENSAJES QUE LLEGUEN A ESTE MODULO 00126 switch(type) 00127 { 00128 case 0: 00129 // LLEGA UN PAQUETE GATE CON IDENTIFICADOR = 0 00130 if(msg->getKind()==0) 00131 { 00132 GATEmsg *gatemsg=check_and_cast<GATEmsg*>(msg); // CHEQUEAMOS EL PAQUETE GATE 00133 00134 // VEMOS SI SE CUMPLEN LAS TRES IGUALDADES PARA QUE SE EJECUTE LA FUNCION: 00135 // SI EL IDENTIFICADOR DE LA DIRECCION DE DESTINO ES IGUAL AL IDENTIFICADOR = 0, 00136 // SI EL TIEMPO DE CREACCION DEL PAQUETE GATE ES MAYOR A 1 SEGUNDO, 00137 // SI EL IDENTIFICADOR DE LA ONU EN LA QUE ESTAMOS ES IGUAL A 0. 00138 if(gatemsg->getDestAddress()==0 && gatemsg->getCreationTime() > 1 && getParentModule()->getIndex()==0) 00139 { 00140 // DAMOS EL VALOR DEL TIEMPO DE SIMULACION A LA VARIABLE time_gate Y LO VISUALIZAMOS POR PANTALLA 00141 time_gate = simTime(); 00142 //ev<<" Tiempo en el que llega el paquete Gate a la ONU 0: "<<time_gate<<"s."<<endl; 00143 //ev<<" Tiempo de envio del paquete Report de la ONU "<<((int)par("numOnu")-1)<<": "<<gatemsg->getTimereport()<<"s."<<endl; 00144 00145 // RECOGIDA DE ESTADISTICAS MANUALMENTE Y LO VISUALIZAMOS POR PANTALLA 00146 comprobar_tiempo_ciclos = time_gate - gatemsg->getTimereport(); // TIEMPO QUE SE PIERDE ENTRE EL FINAL Y EL PRINCIPIO DE UN CICLO 00147 //ev<<" Tiempo que se pierde entre el final y el comienzo de un ciclo: "<<comprobar_tiempo_ciclos<<"s."<<endl; 00148 time_cycles.collect(comprobar_tiempo_ciclos); // RECOGEMOS EL RESULTADO 00149 } 00150 00151 send(gatemsg, "wdmptpOut"); // ENVIAMOS EL PAQUETE GATE HACIA EL MODULO POINT TO POINT DE LA ONU 00152 } 00153 break; 00154 00155 case 1: 00156 // LLEGA UN PAQUETE ETHERNET CON IDENTIFICADOR = 1 00157 if(msg->getKind()==1) 00158 { 00159 // DEFINIMOS EL PARAMETRO ingate QUE NOS INDICA EL PUNTERO DE LA PUERTA POR LA CUAL ENTRA EL MENSAJE QUE LLEGA 00160 cGate *ingate = msg->getArrivalGate(); 00161 00162 // COMPARAMOS EL NOMBRE DE LA PUERTA POR LA QUE ENTRA EL MENSAJE CON LA PUERTA wdmnet$i 00163 if(ingate->getName() == gate("wdmnet$i",intuniform(0,p-1))->getName()) 00164 { 00165 send(msg, "wdmptpOut"); // ENVIAMOS EL PAQUETE ETHERNET HACIA EL MODULO POINT TO POINT DE LA ONU 00166 } 00167 else 00168 { 00169 ETHERNETmsg *ethernetmsg=check_and_cast<ETHERNETmsg*>(msg); // CHEQUEAMOS EL PAQUETE ETHERNET 00170 00171 // VISUALIZAMOS EL TAMA�O DEL PAQUETE ETHERNET QUE MANDAMOS HACIA EL OLT 00172 //ev<<" Longitud del paquete que se manda: "<<ethernetmsg->getByteLength()<<endl; 00173 00174 // CALCULAMOS EL TIEMPO EN EL QUE SE MANDAN LOS PAQUETES ETHERNET JUNTO CON SU TAMA�O EN BITS Y LO VISUALIZAMOS POR PANTALLA 00175 double datarate = ethernetmsg->getByteLength()*8/txrate; // CALCULAMOS EL PARAMETRO datarate QUE INDICA LA TASA DE TRANSMISION DEL PAQUETE ETHERNET 00176 tampacketextract=tampacketextract+ethernetmsg->getByteLength()*8; 00177 timepacketethernet = timepacketethernet + datarate; 00178 //ev<<" Tiempo que tarda en enviarse el paquete ethernet: "<<timepacketethernet<<" s."<<endl; 00179 // ENVIAMOS LOS PAQUETES ETHERNET MEDIANTE EL ENVIO RETARDADO DEL TIEMPO EN EL QUE SE MANDAN LOS PAQUETES 00180 if(ethernetmsg->getIsWireless()==1) 00181 { 00182 ev<<" Envio de paquete Ethernet de origen inalambrico al SPLITTER."<<endl; 00183 } 00184 else 00185 { 00186 sent_messages++; 00187 //ev<<" Envio mensaje Ethernet (Id. " << ethernetmsg->getId() << ") al SPLITTER." << endl; 00188 //ev<<" Total mensajes generados y enviados por esta ONU: " << sent_messages << endl; 00189 } 00190 ethernetmsg->setTime_exit_wdmsplitter(simTime()); 00191 sendDelayed(ethernetmsg, timepacketethernet, "wdmnet$o", ethernetmsg->getLambdaethernet()); 00192 } 00193 } 00194 break; 00195 00196 case 2: 00197 // LLEGA UN PAQUETE REPORT CON IDENTIFICADOR = 2 00198 if(msg->getKind()==2) 00199 { 00200 REPORTmsg *reportmsg=check_and_cast<REPORTmsg*>(msg); // CHEQUEAMOS EL PAQUETE REPORT 00201 00202 lambda=reportmsg->getLambdareport(); 00203 onu=reportmsg->getSrcAddress(); 00204 //ev<<" Envio del paquete report de la ONU "<<onu<< " por la lambda: "<<lambda<<endl; 00205 00206 // ENVIAMOS EL PAQUETE REPORT EN EL INSTANTE DESPUES DE MANDAR TODOS LOS PAQUETES REPORT 00207 sendDelayed(reportmsg, timepacketethernet, "wdmnet$o", lambda); 00208 00209 // COMPARAMOS SI LA DIRECCION FUENTE DEL PAQUETE REPORT ES PARA LA �LTIMA ONU PARA VER EL TIEMPO EN EL QUE SE ENVIA EL REPORT DE LA ULTIMA ONU PARA CALCULAR EL TIEMPO ENTRE CICLOS EN EL METODO DMB DEL OLT 00210 if(reportmsg->getSrcAddress()==((int)par("numOnu")-1)) 00211 { 00212 time_report = reportmsg->getSendingTime(); // TIEMPO EN EL QUE SE ENVIA EL PAQUETE REPORT 00213 reportmsg->setTimesendreport(time_report); // CARGAMOS EL VALOR DE time_report EN UNO DE LOS CAMPOS DEL PAQUETE REPORT Y LO VISUALIZAMOS POR PANTALLA 00214 //ev<<" Tiempo de envio de paquete REPORT de la �ltima ONU: "<<reportmsg->getTimesendreport()<<endl; 00215 } 00216 00217 table_module->bw_asignado=reportmsg->getBandwitch(0); 00218 bw_perdido=(table_module->bw_asignado)*8-tampacketextract; 00219 00220 reportmsg->setBand(bw_perdido); 00221 00222 tampacketextract = 0; 00223 timepacketethernet = 0; // ACTUALIZAMOS EL PARAMETRO DEL TIEMPO DE ENVIO DE LOS PAQUETES ETHERNET AL VALOR 0 00224 } 00225 break; 00226 00227 default: 00228 delete msg; 00229 break; 00230 } 00231 00232 } 00233 00235 //FUNCION FINISH()--> ESTA FUNCION SE INVOCA CUANDO LA SIMULACION HA TERMINADO CON EXITO SIN QUE SE PRODUZCA NINGUN ERROR. // 00236 // LO USAMOS PARA LA RECOGIDA DE ESTADASTICAS Y VISUALIZACION POR PANTALLA O MEDIANTE UN ARCHIVO. // 00238 void ONU_WDMSplitter::finish() 00239 { 00240 //RECOGIDA DE ESTADISTICAS CON LA CLASE ANALISIS!! GUARDAMOS LOS DATOS EN UN ARCHIVO 00241 // SE PONE LA RUTA DONDE SE VAN A CREAR LOS ARCHIVOS 00242 tiempo_entre_ciclos=fopen("results/tiempo_entre_ciclos.txt", "a+"); // ABRIMOS EL ARCHIVO EN EL QUE GUARDAREMOS LOS RESULTADOS 00243 fprintf(tiempo_entre_ciclos,"ONU[%i]: Tiempo medio entre ciclos: %g\n", this->getParentModule()->getIndex(), time_cycles.getMean()); // MEDIA DEL TIEMPO ENTRE CICLOS 00244 fclose(tiempo_entre_ciclos); // CERRAMOS EL ARCHIVO EN EL QUE GUARDAMOS LOS DATOS 00245 00246 }