001package com.net2plan.examples.general.onlineSim; 002/******************************************************************************* 003 * Copyright (c) 2017 Pablo Pavon Marino and others. 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the 2-clause BSD License 006 * which accompanies this distribution, and is available at 007 * https://opensource.org/licenses/BSD-2-Clause 008 * 009 * Contributors: 010 * Pablo Pavon Marino and others - initial API and implementation 011 *******************************************************************************/ 012 013 014import com.net2plan.interfaces.networkDesign.*; 015import com.net2plan.interfaces.simulation.IEventProcessor; 016import com.net2plan.interfaces.simulation.SimEvent; 017import com.net2plan.libraries.IPUtils; 018import com.net2plan.libraries.WDMUtils; 019import com.net2plan.utils.InputParameter; 020import com.net2plan.utils.Triple; 021 022import java.util.HashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027/** 028 * <p>Implements the reactions of an IP over WDM multilayer network, where the IP traffic is carried over lightpaths routed over 029 * a topology of fiber links with a fixed or a flexible wavelength grid.</p> 030 * 031 * <p>The design follows the assumptions described in {@link com.net2plan.libraries.WDMUtils WDMUtils} Net2Plan library</p> 032 * 033 * <p>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 034 * 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 035 * failure processes, propagating the failures and repairs at the WDM layer, as links down/up events in the IP layer.</p> 036 * 037 * <p>The algorithm reacts to the following events:</p> 038 * <ul> 039 * <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> 040 * <li>WDMUtils.LightpathRemove: Removes the corresponding lightpath, releasing the resources and updating both layers.</li> 041 * <li>SimEvent.DemandAdd: (only for the IP layer) Forwards this event to the IP layer module. The target module behaves appropriately.</li> 042 * <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> 043 * <li>SimEvent.DemandRemove: (only for the IP layer) Forwards this event to the IP layer module. The target module behaves appropriately.</li> 044 * <li>SimEvent.NodesAndLinksChangeFailureState: This event is first forwarded to the WDM layer module, with the fails/repairs associated to its layer. Then, the event 045 * 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 046 * 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> 047 * </ul> 048 * 049 * <p>This module can be used in conjunction with the {@code Online_evGen_ipOverWdm} generator for simulating IP over WDM designs.</p> 050 * 051 * <p>See the technology conventions used in Net2Plan built-in algorithms and libraries to represent IP and WDM networks.</p> 052 * @net2plan.keywords IP/OSPF, WDM, Multilayer, Network recovery: protection, Network recovery: restoration 053 * @net2plan.inputParameters 054 * @author Pablo Pavon-Marino 055 */ 056public class Online_evProc_ipOverWdm extends IEventProcessor 057{ 058 private InputParameter wdmNumFrequencySlotsPerFiber = new InputParameter ("wdmNumFrequencySlotsPerFiber", (int) 40 , "Set the number of frequency slots per fiber. If < 1, the number of slots set in the input file is used."); 059 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"); 060 private InputParameter wdmK = new InputParameter ("wdmK", (int) 2 , "Maximum number of admissible paths per demand" , 1 , Integer.MAX_VALUE); 061 private InputParameter wdmRandomSeed = new InputParameter ("wdmRandomSeed", (long) 1 , "Seed for the random generator (-1 means random)"); 062 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"); 063 private InputParameter wdmRemovePreviousLightpaths = new InputParameter ("wdmRemovePreviousLightpaths", false , "If true, previous lightpaths are removed from the system during initialization."); 064// private InputParameter wdmProtectionTypeToNewRoutes = new InputParameter ("wdmProtectionTypeToNewRoutes", "#select# none 1+1-link-disjoint 1+1-node-disjoint 1+1-srg-disjoint" , ""); 065// private InputParameter wdmProtectionTypeIfProtectionToNewRoutes = new InputParameter ("wdmProtectionTypeIfProtectionToNewRoutes", "#select# 1+1-link-disjoint 1+1-node-disjoint 1+1-srg-disjoint" , ""); 066 private InputParameter wdmDefaultAndNewRouteRevoveryType = new InputParameter ("wdmDefaultAndNewRouteRevoveryType", "#select# none restoration 1+1-link-disjoint 1+1-node-disjoint 1+1-srg-disjoint" , "New lightpaths are not protected, or are protected by a 1+1 link disjoint, or a node disjoint or a SRG disjoint lightpath"); 067 private InputParameter wdmTransponderTypesInfo = new InputParameter ("wdmTransponderTypesInfo", "10 1 1 9600 1" , "Transpoder types separated by \";\" . Each type is characterized by the space-separated values: (i) Line rate in Gbps, (ii) cost of the transponder, (iii) number of slots occupied in each traversed fiber, (iv) optical reach in km (a non-positive number means no reach limit), (v) cost of the optical signal regenerator (regenerators do NOT make wavelength conversion ; if negative, regeneration is not possible)."); 068 069 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)"); 070 071// 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."); 072 073 private NetworkLayer wdmLayer , ipLayer; 074 private IEventProcessor ospfNetwork , wdmNetwork; 075 076 @Override 077 public String getDescription() 078 { 079 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"; 080 } 081 082 @Override 083 public List<Triple<String, String, String>> getParameters() 084 { 085 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 086 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 087 } 088 089 @Override 090 public void initialize(NetPlan initialNetPlan, Map<String, String> algorithmParameters, Map<String, String> simulationParameters, Map<String, String> net2planParameters) 091 { 092 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 093 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 094 095 this.ipLayer = initialNetPlan.getNetworkLayer("IP"); if (ipLayer == null) throw new Net2PlanException ("IP layer not found"); 096 this.wdmLayer = initialNetPlan.getNetworkLayer("WDM"); if (wdmLayer == null) throw new Net2PlanException ("WDM layer not found"); 097 if (initialNetPlan.getNumberOfLayers() != 2) throw new Net2PlanException ("The input design must have two layers"); 098 099 this.ospfNetwork = new Online_evProc_ipOspf(); 100 this.wdmNetwork = new Online_evProc_wdm(); 101 102 Map<String,String> wdmParam = InputParameter.createMapFromInputParameters(new InputParameter [] 103 { wdmNumFrequencySlotsPerFiber , wdmRwaType , wdmK , wdmRandomSeed , wdmTransponderTypesInfo , 104 wdmMaxLightpathNumHops , wdmRemovePreviousLightpaths , wdmDefaultAndNewRouteRevoveryType } ); 105 106 this.wdmNetwork.initialize(initialNetPlan , wdmParam , simulationParameters , net2planParameters); 107 108 Map<String,String> ipParam = InputParameter.createMapFromInputParameters(new InputParameter [] { ipMaximumE2ELatencyMs } ); 109 this.ospfNetwork.initialize(initialNetPlan , ipParam , simulationParameters , net2planParameters); 110 111 Set<Link> ipLinksDownBecauseOfWDMLayer = new HashSet<Link> (); for (Link ipLink : initialNetPlan.getLinks (ipLayer)) if (ipLink.getCapacity() == 0) ipLinksDownBecauseOfWDMLayer.add (ipLink); 112 SimEvent.NodesAndLinksChangeFailureState evIp = new SimEvent.NodesAndLinksChangeFailureState(null , null , null , ipLinksDownBecauseOfWDMLayer); 113 ospfNetwork.processEvent(initialNetPlan , new SimEvent(0 , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 114 } 115 116 @Override 117 public void processEvent(NetPlan currentNetPlan, SimEvent event) 118 { 119 /* First, the WDM layer reacts */ 120 if (event.getEventObject () instanceof WDMUtils.LightpathAdd) 121 { 122 WDMUtils.LightpathAdd addLpEvent = (WDMUtils.LightpathAdd) event.getEventObject (); 123 wdmNetwork.processEvent(currentNetPlan , event); 124 if (addLpEvent.lpAddedToFillByProcessor != null) 125 { 126 Route addedLp = addLpEvent.lpAddedToFillByProcessor; 127 /* The lightpath was added */ 128 SimEvent.LinkAdd evIp = new SimEvent.LinkAdd(addLpEvent.ingressNode , addLpEvent.egressNode , ipLayer , addLpEvent.lineRateGbps , addedLp.getLengthInKm() , addedLp.getPropagationSpeedInKmPerSecond()); 129 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 130 if (evIp.linkAddedToFillByProcessor == null) throw new RuntimeException ("Bad"); 131 IPUtils.setLinkWeight(evIp.linkAddedToFillByProcessor , (double) 1); 132 final Demand lpWdmDemand = addedLp.getDemand(); if (lpWdmDemand.getRoutes().size() != 1) throw new Net2PlanException ("Each lightpath must be hosted in its own WDM demand"); 133 lpWdmDemand.coupleToUpperOrSameLayerLink(evIp.linkAddedToFillByProcessor); 134 } 135 } 136 else if (event.getEventObject () instanceof WDMUtils.LightpathRemove) 137 { 138 WDMUtils.LightpathRemove removeLpEvent = (WDMUtils.LightpathRemove) event.getEventObject (); 139 SimEvent.LinkRemove evIp = new SimEvent.LinkRemove(removeLpEvent.lp.getDemand().getCoupledLink()); 140 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 141 SimEvent.DemandRemove evWdmDemandRemove = new SimEvent.DemandRemove(removeLpEvent.lp.getDemand()); 142 wdmNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evWdmDemandRemove)); 143 } 144 else if (event.getEventObject () instanceof SimEvent.DemandModify) 145 { 146 if (((SimEvent.DemandModify) event.getEventObject ()).demand.getLayer() == wdmLayer) wdmNetwork.processEvent(currentNetPlan , event); 147 else if (((SimEvent.DemandModify) event.getEventObject ()).demand.getLayer() == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 148 } 149 /* Events for the IP layer */ 150 else if (event.getEventObject () instanceof SimEvent.DemandAdd) 151 { 152 if (((SimEvent.DemandAdd) event.getEventObject ()).layer == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 153 throw new Net2PlanException ("This algorithm does not handle events of the type DemandAdd, for the WDM layer"); 154 } 155 else if (event.getEventObject () instanceof SimEvent.DemandRemove) 156 { 157 if (((SimEvent.DemandRemove) event.getEventObject ()).demand.getLayer() == ipLayer) ospfNetwork.processEvent(currentNetPlan , event); 158 throw new Net2PlanException ("This algorithm does not handle events of the type DemandRemove, for the WDM layer"); 159 } 160 else if (event.getEventObject () instanceof SimEvent.NodesAndLinksChangeFailureState) 161 { 162 /* each layer processes all node events, and the link events of its layer */ 163 SimEvent.NodesAndLinksChangeFailureState ev = (SimEvent.NodesAndLinksChangeFailureState) event.getEventObject (); 164 Set<Link> ipLinksUp = new HashSet<Link> (); 165 Set<Link> wdmLinksUp = new HashSet<Link> (); 166 Set<Link> ipLinksDown = new HashSet<Link> (); 167 Set<Link> wdmLinksDown = new HashSet<Link> (); 168// System.out.println ("-- ev.linksDown: " + ev.linksDown); 169 170 if (ev.linksToDown != null) for (Link e : ev.linksToDown) if (e.getLayer () == ipLayer) ipLinksDown.add (e); else if (e.getLayer () == wdmLayer) wdmLinksDown.add (e); 171 if (ev.linksToUp != null) for (Link e : ev.linksToUp) if (e.getLayer () == ipLayer) ipLinksUp.add (e); else if (e.getLayer () == wdmLayer) wdmLinksUp.add (e); 172 173// System.out.println ("-- original ip links up: " + ipLinksUp); 174// System.out.println ("-- original ip links down: " + ipLinksDown); 175// System.out.println ("-- original wdm links up: " + wdmLinksUp); 176// System.out.println ("-- original wdm links down: " + wdmLinksDown); 177 178 /* Failures at WDM layer are processed */ 179// System.out.println ("-- process wdm links up/down: " + wdmLinksDown + ", wdmLinksUp: " + wdmLinksUp + ", ev.nodesToUp : " + ev.nodesToUp + ", ev.nodesToDown: " + ev.nodesToDown); 180 SimEvent.NodesAndLinksChangeFailureState evWdm = new SimEvent.NodesAndLinksChangeFailureState(ev.nodesToUp , ev.nodesToDown , wdmLinksUp , wdmLinksDown); 181 wdmNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evWdm)); 182 183 /* Lightpaths with no traffic carried, mean that they are down => OSPF should treat them as down IP links => propagate these failures to IP layer */ 184 Set<Link> ipLinksDownBecauseOfWDMLayer = new HashSet<Link> (); for (Link ipLink : currentNetPlan.getLinks (ipLayer)) if (ipLink.getCapacity() == 0) ipLinksDownBecauseOfWDMLayer.add (ipLink); 185// System.out.println ("-- ipLinksDownBecauseOfWDMLayer: " + ipLinksDownBecauseOfWDMLayer); 186 ipLinksDown.addAll (ipLinksDownBecauseOfWDMLayer); 187// System.out.println ("-- total ipLinksDown: " + ipLinksDown); 188 ipLinksUp = new HashSet<Link> (currentNetPlan.getLinks (ipLayer)); ipLinksUp.removeAll (ipLinksDown); 189// System.out.println ("-- ipLinksUp: " + ipLinksUp); 190// System.out.println ("-- ev.nodesToUp: " + ev.nodesToUp); 191// System.out.println ("-- ev.nodesToDown: " + ev.nodesToDown); 192 SimEvent.NodesAndLinksChangeFailureState evIp = new SimEvent.NodesAndLinksChangeFailureState(ev.nodesToUp , ev.nodesToDown , ipLinksUp , ipLinksDown); 193 ospfNetwork.processEvent(currentNetPlan , new SimEvent(event.getEventTime() , SimEvent.DestinationModule.EVENT_GENERATOR , -1 , evIp)); 194 } 195 else if(event.getEventObject() instanceof WDMUtils.LightpathModify) 196 { 197 wdmNetwork.processEvent(currentNetPlan, new SimEvent(event.getEventTime(), SimEvent.DestinationModule.EVENT_GENERATOR, - 1, (WDMUtils.LightpathModify)event.getEventObject())); 198 } 199 else throw new Net2PlanException ("Unknown event type: " + event); 200 201 } 202 203 204 @Override 205 public String finish(StringBuilder output, double simTime) 206 { 207 output.append ("WDM LAYER OUTPUT"); 208 wdmNetwork.finish(output , simTime); 209 output.append ("<p></p>IP LAYER OUTPUT"); 210 211 ospfNetwork.finish(output , simTime); 212 return ""; 213 } 214 215 @Override 216 public void finishTransitory(double simTime) 217 { 218 wdmNetwork.finishTransitory(simTime); 219 ospfNetwork.finishTransitory(simTime); 220 } 221 222}