blob: d784439d75321558d8e0b90a55af7bb5325c4995 [file] [log] [blame]
package net.onrc.onos.core.intent;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import net.onrc.onos.core.topology.Link;
import net.onrc.onos.core.topology.LinkEvent;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.LinkTuple;
import net.onrc.onos.core.util.PortNumber;
import net.onrc.onos.core.util.SwitchPort;
/**
* In addition to maintaining the Intent ID to Intent mapping of its
* superclass, this class maintains a mapping from switch port to
* PathIntent. It is used to quickly identify Intents that are affected
* when a network event involves a particular switch port.
*/
public class PathIntentMap extends IntentMap {
private final HashMap<Dpid, HashMap<PortNumber, HashSet<PathIntent>>> intents;
/**
* Constructor.
*/
public PathIntentMap() {
intents = new HashMap<>();
}
/**
* Retrieve all PathIntents that contain the specified switch port.
*
* @param swPort the switch port to retrieve Intents for.
* @return a set of all intents that contain swPort
*/
private HashSet<PathIntent> get(SwitchPort swPort) {
Dpid dpid = swPort.getDpid();
PortNumber port = swPort.getPortNumber();
HashMap<PortNumber, HashSet<PathIntent>> portToIntents = intents.get(dpid);
if (portToIntents == null) {
portToIntents = new HashMap<>();
intents.put(dpid, portToIntents);
}
HashSet<PathIntent> targetIntents = portToIntents.get(port);
if (targetIntents == null) {
targetIntents = new HashSet<>();
portToIntents.put(port, targetIntents);
}
return targetIntents;
}
/**
* Add a PathIntent to a particular switch port.
*
* @param swPort switch port
* @param intent Path Intent
*/
private void put(SwitchPort swPort, PathIntent intent) {
get(swPort).add(intent);
}
/**
* Add a PathIntent to the map. The function will automatically
* update the map with all switch ports contained in the Intent.
*
* @param intent the PathIntent
*/
@Override
protected void putIntent(Intent intent) {
if (!(intent instanceof PathIntent)) {
return; // TODO throw exception
}
super.putIntent(intent);
PathIntent pathIntent = (PathIntent) intent;
for (LinkEvent linkEvent : pathIntent.getPath()) {
put(linkEvent.getSrc(), (PathIntent) intent);
put(linkEvent.getDst(), (PathIntent) intent);
}
}
/**
* Removes a PathIntent from the map, including all switch ports.
*
* @param intentId the ID of the PathIntent to be removed
*/
@Override
protected void removeIntent(String intentId) {
PathIntent intent = (PathIntent) getIntent(intentId);
for (LinkEvent linkEvent : intent.getPath()) {
get(linkEvent.getSrc()).remove(intent);
get(linkEvent.getDst()).remove(intent);
}
super.removeIntent(intentId);
}
/**
* Retrieve all intents that use a particular link.
*
* @param linkTuple the link tuple to look up
* @return a collection of PathIntents that use the link
*/
public Collection<PathIntent> getIntentsByLink(LinkTuple linkTuple) {
return getIntentsByPort(
linkTuple.getSrc().getDpid(),
linkTuple.getSrc().getPortNumber());
}
/**
* Retrieve all intents that use a particular port.
*
* @param dpid the switch's DPID
* @param portNumber the switch's port
* @return a collection of PathIntents that use the port
*/
public Collection<PathIntent> getIntentsByPort(Dpid dpid, PortNumber portNumber) {
HashMap<PortNumber, HashSet<PathIntent>> portToIntents = intents.get(dpid);
if (portToIntents != null) {
HashSet<PathIntent> targetIntents = portToIntents.get(portNumber);
if (targetIntents != null) {
return Collections.unmodifiableCollection(targetIntents);
}
}
return new HashSet<>();
}
/**
* Retrieve all intents that use a particular switch.
*
* @param dpid the switch's DPID
* @return a collection of PathIntents that use the switch
*/
public Collection<PathIntent> getIntentsByDpid(Dpid dpid) {
HashSet<PathIntent> result = new HashSet<>();
HashMap<PortNumber, HashSet<PathIntent>> portToIntents = intents.get(dpid);
if (portToIntents != null) {
for (HashSet<PathIntent> targetIntents : portToIntents.values()) {
result.addAll(targetIntents);
}
}
return result;
}
/**
* Calculate available bandwidth of specified link.
*
* @param link the Link
* @return the available bandwidth
*/
public Double getAvailableBandwidth(Link link) {
if (link == null) {
return null;
}
Double bandwidth = link.getCapacity();
if (!bandwidth.isInfinite()) {
for (PathIntent intent : getIntentsByLink(link.getLinkTuple())) {
Double intentBandwidth = intent.getBandwidth();
if (intentBandwidth == null || intentBandwidth.isInfinite() || intentBandwidth.isNaN()) {
continue;
}
bandwidth -= intentBandwidth;
}
}
return bandwidth;
}
}