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