blob: 3c04e0d7c284d6b85759452113f78ac57eb8f751 [file] [log] [blame]
package net.onrc.onos.core.newintent;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import net.onrc.onos.api.flowmanager.FlowId;
import net.onrc.onos.api.flowmanager.FlowLink;
import net.onrc.onos.api.flowmanager.PacketPathFlow;
import net.onrc.onos.api.flowmanager.Path;
import net.onrc.onos.api.newintent.Intent;
import net.onrc.onos.api.newintent.IntentId;
import net.onrc.onos.api.newintent.PointToPointIntent;
import net.onrc.onos.core.intent.ConstrainedBFSTree;
import net.onrc.onos.core.matchaction.action.Action;
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.LinkEvent;
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 static com.google.common.base.Preconditions.checkNotNull;
/**
* A intent compiler for {@link PointToPointIntent}.
*/
public class PointToPointIntentCompiler
extends AbstractFlowGeneratingIntentCompiler<PointToPointIntent> {
private final ITopologyService topologyService;
/**
* Constructs an intent compiler for {@link PointToPointIntent} with the specified
* ID generator and topology service.
*
* @param intentIdGenerator intent ID generator
* @param topologyService topology service
*/
public PointToPointIntentCompiler(IdGenerator<IntentId> intentIdGenerator,
IdGenerator<FlowId> flowIdGenerator,
ITopologyService topologyService) {
super(intentIdGenerator, flowIdGenerator);
this.topologyService = checkNotNull(topologyService);
}
@Override
public List<Intent> compile(PointToPointIntent intent) {
Match match = intent.getMatch();
if (!(match instanceof PacketMatch)) {
throw new IntentCompilationException(
"intent has unsupported type of match object: " + match
);
}
SwitchPort ingress = intent.getIngressPort();
SwitchPort egress = intent.getEgressPort();
FlowId flowId = getNextFlowId();
Path path = calculatePath(ingress, egress);
List<Action> actions = packActions(intent, intent.getEgressPort());
PacketPathFlow flow = new PacketPathFlow(flowId, (PacketMatch) match,
ingress.getPortNumber(), path, actions, 0, 0);
return Arrays.asList((Intent) new PathFlowIntent(getNextId(), flow));
}
/**
* Calculates a path between the specified ingress port and the specified egress port.
* @param ingress ingress port
* @param egress egress port
* @return path
*/
private Path calculatePath(SwitchPort ingress, SwitchPort egress) {
BaseTopology topology = topologyService.getTopology();
Switch source = topology.getSwitch(ingress.getDpid());
Switch destination = topology.getSwitch(egress.getDpid());
if (source == null) {
throw new PathNotFoundException("source switch not found: " + ingress.getDpid());
}
if (destination == null) {
throw new PathNotFoundException("destination switch not found: " + egress.getDpid());
}
ConstrainedBFSTree tree = new ConstrainedBFSTree(source);
net.onrc.onos.core.intent.Path path = tree.getPath(destination);
return convertPath(path);
}
/**
* Converts a {@link net.onrc.onos.core.intent.Path} to {@link Path}.
*
* @param path original {@link net.onrc.onos.core.intent.Path}
* @return converted {@link Path}
*/
static Path convertPath(net.onrc.onos.core.intent.Path path) {
// would like to use filter and transform, but Findbugs detects
// inconsistency of use of @Nullable annotation. Then, use of the
// transform is avoided.
// Ref: https://code.google.com/p/guava-libraries/issues/detail?id=1812
// TODO: replace with transform when the above issue is resolved
ImmutableList<LinkEvent> events = FluentIterable.from(path)
.filter(Predicates.notNull())
.toList();
Path converted = new Path();
for (LinkEvent event: events) {
converted.add(new FlowLink(event.getSrc(), event.getDst()));
}
return converted;
}
}