blob: dc1f50c49887ee245a6b72a385567fda557269bc [file] [log] [blame]
package net.onrc.onos.core.newintent;
import net.onrc.onos.api.flowmanager.FlowId;
import net.onrc.onos.api.flowmanager.SingleDstTreeFlow;
import net.onrc.onos.api.flowmanager.Tree;
import net.onrc.onos.api.newintent.Intent;
import net.onrc.onos.api.newintent.IntentId;
import net.onrc.onos.api.newintent.MultiPointToSinglePointIntent;
import net.onrc.onos.core.intent.ConstrainedBFSTree;
import net.onrc.onos.core.intent.Path;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.matchaction.match.PacketMatch;
import net.onrc.onos.core.topology.BaseTopology;
import net.onrc.onos.core.topology.ITopologyService;
import net.onrc.onos.core.topology.Switch;
import net.onrc.onos.core.util.IdGenerator;
import net.onrc.onos.core.util.SwitchPort;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static net.onrc.onos.core.newintent.PointToPointIntentCompiler.convertPath;
/**
* An intent compiler for {@link MultiPointToSinglePointIntent}.
*/
public class MultiPointToSinglePointIntentCompiler
extends AbstractFlowGeneratingIntentCompiler<MultiPointToSinglePointIntent> {
private final ITopologyService topologyService;
/**
* Constructs an intent compiler for {@link MultiPointToSinglePointIntent}.
*
* @param intentIdGenerator intent ID generator
* @param flowIdGenerator flow ID generator
* @param topologyService topology service
*/
public MultiPointToSinglePointIntentCompiler(IdGenerator<IntentId> intentIdGenerator,
IdGenerator<FlowId> flowIdGenerator,
ITopologyService topologyService) {
super(intentIdGenerator, flowIdGenerator);
this.topologyService = checkNotNull(topologyService);
}
@Override
public List<Intent> compile(MultiPointToSinglePointIntent intent) {
Match match = intent.getMatch();
if (!(match instanceof PacketMatch)) {
throw new IntentCompilationException(
"intent has unsupported type of match object: " + match
);
}
SingleDstTreeFlow treeFlow = new SingleDstTreeFlow(
getNextFlowId(),
(PacketMatch) intent.getMatch(), // down-cast, but it is safe due to the guard above
intent.getIngressPorts(),
calculateTree(intent.getIngressPorts(), intent.getEgressPort()),
packActions(intent, intent.getEgressPort())
);
Intent compiled = new SingleDstTreeFlowIntent(getNextId(), treeFlow);
return Arrays.asList(compiled);
}
/**
* Calculates a tree with the specified ingress ports and egress port.
*
* {@link PathNotFoundException} is thrown when no tree found or
* the specified egress port is not found in the topology.
*
* @param ingressPorts ingress ports
* @param egressPort egress port
* @return tree
* @throws PathNotFoundException if the specified egress switch is not
* found or no tree is found.
*/
private Tree calculateTree(Set<SwitchPort> ingressPorts, SwitchPort egressPort) {
BaseTopology topology = topologyService.getTopology();
Switch egressSwitch = topology.getSwitch(egressPort.getDpid());
if (egressSwitch == null) {
throw new PathNotFoundException("destination switch not found: " + egressPort.getDpid());
}
ConstrainedBFSTree bfs = new ConstrainedBFSTree(egressSwitch);
Tree tree = new Tree();
for (SwitchPort ingressPort : ingressPorts) {
Switch ingressSwitch = topology.getSwitch(ingressPort.getDpid());
if (ingressSwitch == null) {
continue;
}
Path path = bfs.getPath(ingressSwitch);
if (path.isEmpty()) {
continue;
}
tree.addAll(convertPath(path));
}
if (tree.isEmpty()) {
throw new PathNotFoundException(
String.format("No tree found (ingress: %s, egress: %s", ingressPorts, egressPort)
);
}
return tree;
}
}