001/******************************************************************************* 002 * Copyright (c) 2016 Pablo Pavon Mariņo. 003 * All rights reserved. This program and the accompanying materials 004 * are made available under the terms of the GNU Lesser Public License v2.1 005 * which accompanies this distribution, and is available at 006 * http://www.gnu.org/licenses/lgpl.html 007 ******************************************************************************/ 008 009 010 011 012 013 014 015 016 017 018package com.net2plan.examples.general.onlineSim; 019 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import com.net2plan.interfaces.networkDesign.Demand; 026import com.net2plan.interfaces.networkDesign.Link; 027import com.net2plan.interfaces.networkDesign.Net2PlanException; 028import com.net2plan.interfaces.networkDesign.NetPlan; 029import com.net2plan.interfaces.networkDesign.NetworkLayer; 030import com.net2plan.interfaces.networkDesign.Route; 031import com.net2plan.interfaces.simulation.IEventProcessor; 032import com.net2plan.interfaces.simulation.SimEvent; 033import com.net2plan.libraries.IPUtils; 034import com.net2plan.libraries.WDMUtils; 035import com.net2plan.utils.InputParameter; 036import com.net2plan.utils.Triple; 037 038/** 039 * Implements the reactions of an IP over WDM multilayer network, where the IP traffic is carried over fixed rate lightpaths, routed over a topology of fiber links with a fixed wavelength grid 040 * 041 * This algorithm implements the reactions of an IP over WDM multilayer network. Internally, the algorithm just coordinates the reactions of the WDM layer and the 042 * IP layer, each of them implemented by the {@code Online_evProv_wdm} and {@code Online_evProc_ipOspf} modules. The coordination actions are basically during the 043 * failure processes, propagating the failures and repairs at the WDM layer, as links down/up events in the IP layer. 044 * 045 * The algorithm reacts to the following events: 046 * <ul> 047 * <li>WDMUtils.LightpathAdd: Adds the corresponding lightpath to the network, if enough resources exist for it, calling to the WDM layer module. If so, it is added also as an IP link, and the IP routing modified, by calling the IP module.</li> 048 * <li>WDMUtils.LightpathRemove: Removes the corresponding lightpath, releasing the resources and updating both layers.</li> 049 * <li>SimEvent.DemandAdd: (only for the IP layer) Forwards this event to the IP layer module. The target module behaves appropriately.</li> 050 * <li>SimEvent.DemandModify: Forwards this event to the WDM or IP layer modules, depending on the event associated layer. The target module behaves appropriately.</li> 051 * <li>SimEvent.DemandRemove: (only for the IP layer) Forwards this event to the IP layer module. The target module behaves appropriately.</li> 052 * <li>SimEvent.NodesAndLinksChangeFailureState: This event is first forwarded to the WDM layer module, with the fails/repairs associated to its layer. Then, the event 053 * is sent to the IP layer, updating the IP links failures and repairs, depending on the results of the WDM layer. For instance, any WDM failures that result in a WDM 054 * demand carrying no traffic (affected by a failure for which it could not recover), is propagated to the IP layer as a failing IP link.</li> 055 * </ul> 056 * 057 * This module can be used in conjunction with the {@code Online_evGen_ipOverWdm} generator for simulating IP over WDM designs. 058 * 059 * See the technology conventions used in Net2Plan built-in algorithms and libraries to represent IP and WDM networks. 060 * @net2plan.keywords IP/OSPF, WDM, Multilayer, Network recovery: protection, Network recovery: restoration 061 * @net2plan.inputParameters 062 * @author Pablo Pavon-Marino, Jose-Luis Izquierdo-Zaragoza 063 */ 064public class Online_evProc_ipOverWdm extends IEventProcessor 065{ 066 private InputParameter wdmNumWavelengthsPerFiber = new InputParameter ("wdmNumWavelengthsPerFiber", (int) 40 , "Set the number of wavelengths per link. If < 1, the number of wavelengths set in the input file is used."); 067 private InputParameter wdmRwaType = new InputParameter ("wdmRwaType", "#select# srg-disjointness-aware-route-first-fit alternate-routing least-congested-routing load-sharing" , "Criteria to decide the route of a connection among the available paths"); 068 private InputParameter wdmKShortestPathType = new InputParameter ("wdmKShortestPathType", "#select# hops km" , "Criteria to compute the shortest path. Valid values: 'hops' or 'km'"); 069 private InputParameter wdmK = new InputParameter ("wdmK", (int) 2 , "Maximum number of admissible paths per demand" , 1 , Integer.MAX_VALUE); 070 private InputParameter wdmRandomSeed = new InputParameter ("wdmRandomSeed", (long) 1 , "Seed for the random generator (-1 means random)"); 071 private InputParameter wdmMaxLightpathLengthInKm = new InputParameter ("wdmMaxLightpathLengthInKm", (double) -1 , "Lightpaths longer than this are considered not admissible. A non-positive number means this limit does not exist"); 072 private InputParameter wdmMaxLightpathNumHops = new InputParameter ("wdmMaxLightpathNumHops", (int) -1 , "A lightpath cannot have more than this number of hops. A non-positive number means this limit does not exist"); 073 private InputParameter wdmLayerIndex = new InputParameter ("wdmLayerIndex", (int) 0 , "Index of the WDM layer (-1 means default layer)"); 074 private InputParameter wdmRemovePreviousLightpaths = new InputParameter ("wdmRemovePreviousLightpaths", false , "If true, previous lightpaths are removed from the system during initialization."); 075 private InputParameter wdmProtectionTypeToNewRoutes = new InputParameter ("wdmProtectionTypeToNewRoutes", "#select# none 1+1-link-disjoint 1+1-node-disjoint 1+1-srg-disjoint" , ""); 076 private InputParameter wdmLineRatePerLightpath_Gbps = new InputParameter ("wdmLineRatePerLightpath_Gbps", (double) 40 , "All the lightpaths have this carried traffic by default, when a lightpath is added and this quantity is not specified in the add lightpath event" , 0 , false , Double.MAX_VALUE , true); 077 078 private InputParameter ipLayerIndex = new InputParameter ("ipLayerIndex", (int) 1 , "Index of the layer containing IP network (-1 means default layer)"); 079 private InputParameter ipMaximumE2ELatencyMs = new InputParameter ("ipMaximumE2ELatencyMs", (double) -1 , "Maximum end-to-end latency of the traffic of an IP demand to consider it as lost traffic (a non-positive value means no limit)"); 080 081 private InputParameter ipOverWdmNetworkRecoveryType = new InputParameter ("ipOverWdmNetworkRecoveryType", "#select# static-lps-OSPF-rerouting 1+1-lps-OSPF-rerouting lp-restoration-OSPF-rerouting" , "The recovery type the network will apply. If static lps, the VT is overdimensioned to tolerate single SRG failures. In the 1+1 case, link disjoit backup lps are created. If lps are 1+1 protected or have lp restoration, the VT is dimensioned to carry all IP traffic in the no failure state."); 082 083 private NetworkLayer wdmLayer , ipLayer; 084 private IEventProcessor ospfNetwork , wdmNetwork; 085 086 @Override 087 public String getDescription() 088 { 089 return "Implements the reactions of an IP over WDM multilayer network, where the IP traffic is carried over fixed rate lightpaths, routed over a topology of fiber links with a fixed wavelength grid"; 090 } 091 092 @Override 093 public List<Triple<String, String, String>> getParameters() 094 { 095 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 096 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 097 } 098 099 @Override 100 public void initialize(NetPlan initialNetPlan, Map<String, String> algorithmParameters, Map<String, String> simulationParameters, Map<String, String> net2planParameters) 101 { 102 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 103// System.out.println ("IP over WDM algoritm params: " + algorithmParameters); 104 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 105 if (!ipOverWdmNetworkRecoveryType.getString().equals("1+1-lps-OSPF-rerouting") && !wdmProtectionTypeToNewRoutes.getString().equals ("none")) throw new Net2PlanException ("The type of 1+1 protection can only be specified in network recovery uses lightpath protection"); 106 107 this.ipLayer = ipLayerIndex.getInt () == -1? initialNetPlan.getNetworkLayerDefault() : initialNetPlan.getNetworkLayer(ipLayerIndex.getInt ()); 108 this.wdmLayer = wdmLayerIndex.getInt () == -1? initialNetPlan.getNetworkLayerDefault() : initialNetPlan.getNetworkLayer(wdmLayerIndex.getInt ()); 109 if (initialNetPlan.getNumberOfLayers() != 2) throw new Net2PlanException ("The input design must have two layers"); 110 if (ipLayer == wdmLayer) throw new Net2PlanException ("IP layer and/or WDM layer ids are wrong"); 111 112 this.ospfNetwork = new Online_evProc_ipOspf(); 113 this.wdmNetwork = new Online_evProc_wdm(); 114 115 Map<String,String> wdmParam = InputParameter.createMapFromInputParameters(new InputParameter [] 116 { wdmNumWavelengthsPerFiber , wdmRwaType , wdmKShortestPathType , wdmK , wdmRandomSeed , wdmMaxLightpathLengthInKm , 117 wdmMaxLightpathNumHops , wdmLayerIndex , wdmRemovePreviousLightpaths , wdmLineRatePerLightpath_Gbps } ); 118 String wdmRecoveryType , wdmProtectionTypeToNewRoutes_st; 119 if (ipOverWdmNetworkRecoveryType.getString ().equals ("static-lps-OSPF-rerouting")) { wdmRecoveryType = "none"; wdmProtectionTypeToNewRoutes_st = "none"; } 120 else if (ipOverWdmNetworkRecoveryType.getString ().equals ("1+1-lps-OSPF-rerouting")) { wdmRecoveryType = "protection"; wdmProtectionTypeToNewRoutes_st = wdmProtectionTypeToNewRoutes.getString (); } 121 else if (ipOverWdmNetworkRecoveryType.getString ().equals ("lp-restoration-OSPF-rerouting")) {wdmRecoveryType = "restoration"; wdmProtectionTypeToNewRoutes_st = "none"; } 122 else throw new RuntimeException ("Bad"); 123 wdmParam.put ("wdmRecoveryType" , wdmRecoveryType); 124 wdmParam.put ("wdmProtectionTypeToNewRoutes" , wdmProtectionTypeToNewRoutes_st); 125 this.wdmNetwork.initialize(initialNetPlan , wdmParam , simulationParameters , net2planParameters); 126 127 Map<String,String> ipParam = InputParameter.createMapFromInputParameters(new InputParameter [] { ipLayerIndex , ipMaximumE2ELatencyMs } ); 128 this.ospfNetwork.initialize(initialNetPlan , ipParam , simulationParameters , net2planParameters); 129 130 Set<Link> ipLinksDownBecauseOfWDMLayer = new HashSet<Link> (); for (Link ipLink : initialNetPlan.getLinks (ipLayer)) if (ipLink.getCapacity() == 0) ipLinksDownBecauseOfWDMLayer.add (ipLink); 131 SimEvent.NodesAndLinksChangeFailureState evIp = new SimEvent.NodesAndLinksChangeFailureState(null , null , null , ipLinksDownBecauseOfWDMLayer); 132 ospfNetwork.processEvent(initialNetPlan , new SimEvent(0 , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 133} 134 135 @Override 136 public void processEvent(NetPlan currentNetPlan, SimEvent event) 137 { 138 /* First, the WDM layer reacts */ 139 if (event.getEventObject () instanceof WDMUtils.LightpathAdd) 140 { 141 WDMUtils.LightpathAdd addLpEvent = (WDMUtils.LightpathAdd) event.getEventObject (); 142 wdmNetwork.processEvent(currentNetPlan , event); 143 if (addLpEvent.lpAddedToFillByProcessor != null) 144 { 145 Route addedLp = addLpEvent.lpAddedToFillByProcessor; 146 /* The lightpath was added */ 147 SimEvent.LinkAdd evIp = new SimEvent.LinkAdd(addLpEvent.ingressNode , addLpEvent.egressNode , ipLayer , wdmLineRatePerLightpath_Gbps.getDouble() , addedLp.getLengthInKm() , addedLp.getPropagationSpeedInKmPerSecond()); 148 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 149 if (evIp.linkAddedToFillByProcessor == null) throw new RuntimeException ("Bad"); 150 IPUtils.setLinkWeight(evIp.linkAddedToFillByProcessor , (double) 1); 151 final Demand lpWdmDemand = addedLp.getDemand(); if (lpWdmDemand.getRoutes().size() != 1) throw new Net2PlanException ("Each lightpath must be hosted in its own WDM demand"); 152 lpWdmDemand.coupleToUpperLayerLink(evIp.linkAddedToFillByProcessor); 153 } 154 } 155 else if (event.getEventObject () instanceof WDMUtils.LightpathRemove) 156 { 157 WDMUtils.LightpathRemove removeLpEvent = (WDMUtils.LightpathRemove) event.getEventObject (); 158 SimEvent.LinkRemove evIp = new SimEvent.LinkRemove(removeLpEvent.lp.getDemand().getCoupledLink()); 159 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 160 SimEvent.DemandRemove evWdmDemandRemove = new SimEvent.DemandRemove(removeLpEvent.lp.getDemand()); 161 wdmNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evWdmDemandRemove)); 162 } 163 else if (event.getEventObject () instanceof SimEvent.DemandModify) 164 { 165 if (((SimEvent.DemandModify) event.getEventObject ()).demand.getLayer() == wdmLayer) wdmNetwork.processEvent(currentNetPlan , event); 166 else if (((SimEvent.DemandModify) event.getEventObject ()).demand.getLayer() == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 167 } 168 /* Events for the IP layer */ 169 else if (event.getEventObject () instanceof SimEvent.DemandAdd) 170 { 171 if (((SimEvent.DemandAdd) event.getEventObject ()).layer == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 172 throw new Net2PlanException ("This algorithm does not handle events of the type DemandAdd, for the WDM layer"); 173 } 174 else if (event.getEventObject () instanceof SimEvent.DemandRemove) 175 { 176 if (((SimEvent.DemandRemove) event.getEventObject ()).demand.getLayer() == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 177 throw new Net2PlanException ("This algorithm does not handle events of the type DemandRemove, for the WDM layer"); 178 } 179 else if (event.getEventObject () instanceof SimEvent.NodesAndLinksChangeFailureState) 180 { 181 /* each layer processes all node events, and the link events of its layer */ 182 SimEvent.NodesAndLinksChangeFailureState ev = (SimEvent.NodesAndLinksChangeFailureState) event.getEventObject (); 183 Set<Link> ipLinksUp = new HashSet<Link> (); 184 Set<Link> wdmLinksUp = new HashSet<Link> (); 185 Set<Link> ipLinksDown = new HashSet<Link> (); 186 Set<Link> wdmLinksDown = new HashSet<Link> (); 187// System.out.println ("-- ev.linksDown: " + ev.linksDown); 188 189 if (ev.linksToDown != null) for (Link e : ev.linksToDown) if (e.getLayer () == ipLayer) ipLinksDown.add (e); else if (e.getLayer () == wdmLayer) wdmLinksDown.add (e); 190 if (ev.linksToUp != null) for (Link e : ev.linksToUp) if (e.getLayer () == ipLayer) ipLinksUp.add (e); else if (e.getLayer () == wdmLayer) wdmLinksUp.add (e); 191 192// System.out.println ("-- original ip links up: " + ipLinksUp); 193// System.out.println ("-- original ip links down: " + ipLinksDown); 194// System.out.println ("-- original wdm links up: " + wdmLinksUp); 195// System.out.println ("-- original wdm links down: " + wdmLinksDown); 196 197 /* Failures at WDM layer are processed */ 198// System.out.println ("-- process wdm links up/down: " + wdmLinksDown + ", wdmLinksUp: " + wdmLinksUp + ", ev.nodesToUp : " + ev.nodesToUp + ", ev.nodesToDown: " + ev.nodesToDown); 199 SimEvent.NodesAndLinksChangeFailureState evWdm = new SimEvent.NodesAndLinksChangeFailureState(ev.nodesToUp , ev.nodesToDown , wdmLinksUp , wdmLinksDown); 200 wdmNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evWdm)); 201 202 /* Lightpaths with no traffic carried, mean that they are down => OSPF should treat them as down IP links => propagate these failures to IP layer */ 203 Set<Link> ipLinksDownBecauseOfWDMLayer = new HashSet<Link> (); for (Link ipLink : currentNetPlan.getLinks (ipLayer)) if (ipLink.getCapacity() == 0) ipLinksDownBecauseOfWDMLayer.add (ipLink); 204// System.out.println ("-- ipLinksDownBecauseOfWDMLayer: " + ipLinksDownBecauseOfWDMLayer); 205 ipLinksDown.addAll (ipLinksDownBecauseOfWDMLayer); 206// System.out.println ("-- total ipLinksDown: " + ipLinksDown); 207 ipLinksUp = new HashSet<Link> (currentNetPlan.getLinks (ipLayer)); ipLinksUp.removeAll (ipLinksDown); 208// System.out.println ("-- ipLinksUp: " + ipLinksUp); 209// System.out.println ("-- ev.nodesToUp: " + ev.nodesToUp); 210// System.out.println ("-- ev.nodesToDown: " + ev.nodesToDown); 211 SimEvent.NodesAndLinksChangeFailureState evIp = new SimEvent.NodesAndLinksChangeFailureState(ev.nodesToUp , ev.nodesToDown , ipLinksUp , ipLinksDown); 212 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 213 } 214 else throw new Net2PlanException ("Unknown event type: " + event); 215 216 } 217 218 219 @Override 220 public String finish(StringBuilder output, double simTime) 221 { 222 output.append ("WDM LAYER OUTPUT"); 223 wdmNetwork.finish(output , simTime); 224 output.append ("<p></p>IP LAYER OUTPUT"); 225 226 ospfNetwork.finish(output , simTime); 227 return ""; 228 } 229 230 @Override 231 public void finishTransitory(double simTime) 232 { 233 wdmNetwork.finishTransitory(simTime); 234 ospfNetwork.finishTransitory(simTime); 235 } 236 237}