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 018 019package com.net2plan.examples.general.onlineSim; 020 021import java.util.List; 022import java.util.Map; 023 024import cern.colt.function.tdouble.DoubleDoubleFunction; 025import cern.colt.matrix.tdouble.DoubleMatrix1D; 026 027import com.net2plan.interfaces.networkDesign.Demand; 028import com.net2plan.interfaces.networkDesign.Link; 029import com.net2plan.interfaces.networkDesign.Net2PlanException; 030import com.net2plan.interfaces.networkDesign.NetPlan; 031import com.net2plan.interfaces.networkDesign.NetworkLayer; 032import com.net2plan.interfaces.simulation.IEventProcessor; 033import com.net2plan.interfaces.simulation.SimEvent; 034import com.net2plan.libraries.IPUtils; 035import com.net2plan.utils.Constants.RoutingType; 036import com.net2plan.utils.InputParameter; 037import com.net2plan.utils.Triple; 038 039/** 040 * Implements the reactions of an IP network governed by the OSPF/ECMP forwarding policies, for given link weigths 041 * 042 * This algorithm implements the reactions of an IP network governed by the OSPF/ECMP forwarding policies, for given link weigths, to the following events: 043 * <ul> 044 * <li>SimEvent.DemandAdd: Adds a new IP traffic demand, and recomputes the routing (now including the new traffic).</li> 045 * <li>SimEvent.DemandRemove: Remvoes an IP traffic demand, and recomputes the routing.</li> 046 * <li>SimEvent.DemandModify: Modifies the offered traffic of a demand, and recomputes the routing.</li> 047 * <li>SimEvent.LinkAdd: Adds a new IP link to the network, recomputes the routing tables and the routing.</li> 048 * <li>SimEvent.LinkRemove: Removes an existing IP link in the network, recomputes the routing tables and the routing.</li> 049 * <li>SimEvent.LinkModify: Modifies the capacity of an IP link. The routing is not modified, since OSPF does not react to capacity changes.</li> 050 * <li>SimEvent.NodesAndLinksChangeFailureState: Fails/repairs the indicated nodes and/or IP links, and reacts to such failures as OSPF does: the failed links are removed from the routing tables, and the network routing recomputed.</li> 051 * </ul> 052 * 053 * This module can be used in conjunction with the {@code Online_evGen_generalGenerator} generator for simulating IP/OSPF networks. 054 * 055 * See the technology conventions used in Net2Plan built-in algorithms and libraries to represent IP/OSPF networks. 056 * @net2plan.keywords IP/OSPF, Network recovery: restoration 057 * @net2plan.inputParameters 058 * @author Pablo Pavon-Marino, Jose-Luis Izquierdo-Zaragoza 059 */ 060public class Online_evProc_ipOspf extends IEventProcessor 061{ 062 private InputParameter ipLayerIndex = new InputParameter ("ipLayerIndex", (int) -1 , "Index of the layer containing IP network (-1 means default layer)"); 063 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)"); 064 private NetworkLayer ipLayer; 065 private double stat_trafficOffered , stat_trafficCarried , stat_trafficOversubscribed , stat_trafficOutOfLatencyLimit , stat_trafficOfDemandsTraversingOversubscribedLink; 066 private double stat_transitoryInitTime , stat_timeLastChangeInNetwork; 067 068 @Override 069 public String getDescription() 070 { 071 return "Implements the reactions of an IP network governed by the OSPF/ECMP forwarding policies, for given link weigths"; 072 } 073 074 @Override 075 public List<Triple<String, String, String>> getParameters() 076 { 077 /* Returns the parameter information for all the InputParameter objects defined in this object (uses Java reflection) */ 078 return InputParameter.getInformationAllInputParameterFieldsOfObject(this); 079 } 080 081 @Override 082 public void initialize(NetPlan initialNetPlan, Map<String, String> algorithmParameters, Map<String, String> simulationParameters, Map<String, String> net2planParameters) 083 { 084 /* Initialize all InputParameter objects defined in this object (this uses Java reflection) */ 085 InputParameter.initializeAllInputParameterFieldsOfObject(this, algorithmParameters); 086 087 this.ipLayer = (ipLayerIndex.getInt() == -1)? initialNetPlan.getNetworkLayerDefault() : initialNetPlan.getNetworkLayer(ipLayerIndex.getInt ()); 088 if (ipLayer == null) throw new Net2PlanException ("Unknown layer id"); 089 090 initialNetPlan.setRoutingType(RoutingType.HOP_BY_HOP_ROUTING , ipLayer); 091 DoubleMatrix1D linkIGPWeightSetting = IPUtils.getLinkWeightVector(initialNetPlan , ipLayer); 092 linkIGPWeightSetting.assign (initialNetPlan.getVectorLinkUpState(ipLayer) , new DoubleDoubleFunction () { public double apply (double x , double y) { return y == 1? x : Double.MAX_VALUE; } } ); 093 IPUtils.setECMPForwardingRulesFromLinkWeights(initialNetPlan , linkIGPWeightSetting , ipLayer); 094 095 finishTransitory(0); 096 stat_timeLastChangeInNetwork = 0; 097 } 098 099 @Override 100 public void processEvent(NetPlan currentNetPlan, SimEvent event) 101 { 102 /* Update with the network stage since the last event until now */ 103 final double timeSinceLastChange = event.getEventTime() - stat_timeLastChangeInNetwork; 104 stat_trafficOffered += timeSinceLastChange * currentNetPlan.getVectorDemandOfferedTraffic(this.ipLayer).zSum(); 105 stat_trafficCarried += timeSinceLastChange * currentNetPlan.getVectorDemandCarriedTraffic(this.ipLayer).zSum(); 106 stat_trafficOversubscribed += timeSinceLastChange * currentNetPlan.getVectorLinkOversubscribedTraffic(this.ipLayer).zSum(); 107 stat_trafficOfDemandsTraversingOversubscribedLink += timeSinceLastChange * currentNetPlan.getVectorDemandOfferedTraffic(this.ipLayer).zDotProduct(currentNetPlan.getVectorDemandTraversesOversubscribedLink(this.ipLayer)); 108 if (ipMaximumE2ELatencyMs.getDouble () > 0) for (Demand d : currentNetPlan.getDemands (ipLayer)) if (d.getWorseCasePropagationTimeInMs() > ipMaximumE2ELatencyMs.getDouble ()) stat_trafficOutOfLatencyLimit += timeSinceLastChange * d.getOfferedTraffic(); 109 110 stat_timeLastChangeInNetwork = event.getEventTime(); 111 112 if (event.getEventObject () instanceof SimEvent.DemandAdd) 113 { 114 SimEvent.DemandAdd ev = (SimEvent.DemandAdd) event.getEventObject (); 115 Demand d = currentNetPlan.addDemand(ev.ingressNode, ev.egressNode, ev.offeredTraffic, null, ev.layer); 116 ev.demandAddedToFillByProcessor = d; 117 } else if (event.getEventObject () instanceof SimEvent.DemandRemove) 118 { 119 SimEvent.DemandRemove ev = (SimEvent.DemandRemove) event.getEventObject (); 120 ev.demand.remove (); 121 } else if (event.getEventObject () instanceof SimEvent.DemandModify) 122 { 123 SimEvent.DemandModify ev = (SimEvent.DemandModify) event.getEventObject (); 124 Demand d = ev.demand; 125// System.out.print ("IPOSPF DemandModify: demand " + d + ", " + (ev.modificationIsRelativeToCurrentOfferedTraffic? "RELATIVE" : "ABSOLUTE") + " , old demand offered: " + d.getOfferedTraffic() + " "); 126 if (ev.modificationIsRelativeToCurrentOfferedTraffic) 127 d.setOfferedTraffic(d.getOfferedTraffic() + ev.offeredTraffic); 128 else 129 d.setOfferedTraffic(ev.offeredTraffic); 130 System.out.println (" new demand offered: " + d.getOfferedTraffic()); 131 } else if (event.getEventObject () instanceof SimEvent.LinkAdd) 132 { 133 SimEvent.LinkAdd ev = (SimEvent.LinkAdd) event.getEventObject (); 134 Link newLink = currentNetPlan.addLink (ev.originNode , ev.destinationNode, ev.capacity , ev.lengthInKm , ev.propagationSpeedInKmPerSecond , null , ev.layer); 135 ev.linkAddedToFillByProcessor = newLink; 136 } else if (event.getEventObject () instanceof SimEvent.LinkRemove) 137 { 138 SimEvent.LinkRemove ev = (SimEvent.LinkRemove) event.getEventObject (); 139 ev.link.remove(); 140 } else if (event.getEventObject () instanceof SimEvent.LinkModify) 141 { 142 SimEvent.LinkModify ev = (SimEvent.LinkModify) event.getEventObject (); 143 ev.link.setCapacity(ev.newCapacity); 144 } else if (event.getEventObject () instanceof SimEvent.NodesAndLinksChangeFailureState) 145 { 146 SimEvent.NodesAndLinksChangeFailureState ev = (SimEvent.NodesAndLinksChangeFailureState) event.getEventObject (); 147 currentNetPlan.setLinksAndNodesFailureState(ev.linksToUp , ev.linksToDown , ev.nodesToUp , ev.nodesToDown); 148 } 149 else throw new Net2PlanException ("Unknown event type: " + event); 150 151 /* Link weights from netPlan, but the down links have Double.MAX_VALUE weight */ 152 DoubleMatrix1D linkIGPWeightSetting = IPUtils.getLinkWeightVector(currentNetPlan , ipLayer); 153 linkIGPWeightSetting.assign (currentNetPlan.getVectorLinkUpState(ipLayer) , new DoubleDoubleFunction () { public double apply (double x , double y) { return y == 1? x : Double.MAX_VALUE; } } ); 154 IPUtils.setECMPForwardingRulesFromLinkWeights(currentNetPlan , linkIGPWeightSetting , ipLayer); 155// System.out.println ("-- CHANGE OSPF ROUTING: linkIGPWeightSetting: " + linkIGPWeightSetting); 156 } 157 158 @Override 159 public void finishTransitory(double simTime) 160 { 161 this.stat_trafficOffered = 0; 162 this.stat_trafficCarried = 0; 163 this.stat_trafficOversubscribed = 0; 164 this.stat_trafficOutOfLatencyLimit = 0; 165 this.stat_trafficOfDemandsTraversingOversubscribedLink = 0; 166 this.stat_transitoryInitTime = simTime; 167 } 168 169 @Override 170 public String finish(StringBuilder output, double simTime) 171 { 172 final double dataTime = simTime - stat_transitoryInitTime; 173 if (dataTime <= 0) { output.append ("<p>No time for data acquisition</p>"); return ""; } 174 output.append (String.format("<p>Time average traffic offered / carried / blocking (%f , %f , %f) </p>", stat_trafficOffered / dataTime, stat_trafficCarried / dataTime , stat_trafficOffered == 0? 0 : 1 - (stat_trafficCarried / stat_trafficOffered))); 175 output.append (String.format("<p>Time average traffic oversubscribed: %f (sum traffic oversubscription in the links) </p>", stat_trafficOversubscribed / dataTime)); 176 output.append (String.format("<p>Time average traffic of demands with worse case propagation time out of latency limits: %f</p>", stat_trafficOutOfLatencyLimit / dataTime)); 177 output.append (String.format("<p>Time average traffic of demands which traverse an oversubscribed link (summing all the demand offered traffic, even if only a fraction of traffic traverses oversubscribed links): %f</p>", stat_trafficOfDemandsTraversingOversubscribedLink / dataTime)); 178 return ""; 179 } 180}